JavaScript勉強会

JavaScriptの学習日記

JavaScript関数型プログラミング 複雑性を抑える発想と実践法を学ぶ 【目次】

JavaScriptで学ぶ「関数型プログラミング」の本がありました。

JavaScript関数型プログラミング」という本です。

本屋で立ち読みしたら、面白そうだったので買っちゃいましたw

 

JavaScript関数型プログラミング 複雑性を抑える発想と実践法を学ぶ (impress top gear)

JavaScript関数型プログラミング 複雑性を抑える発想と実践法を学ぶ (impress top gear)

 

 

 

目次

序文

本書について

謝辞

 

■Part1 発想の転換とキーコンセプト

第1章 関数型で思考する

1.1 関数型プログラミングを学ぶと役に立つのか?

1.2 関数型プログラミングとは何か

 1.2.1 関数型プログラミングは宣言型である

 1.2.2 純粋関数と副作用問題

 1.2.3 参照透過性と代替性

 1.2.4 データの不変性を維持

1.3 関数型プログラミングの利点

 1.3.1 タスクをシンプルな関数に分解する

 1.3.2 円滑なチェーンを使ってデータ処理

 1.3.3 非同期アプリケーションの複雑性に対処する

1.4 まとめ

 

第2章 関数型言語としてのJavaScript

2.1 なぜJavaScriptなのか

2.2 関数型プログラミング vs. オブジェクト指向プログラミング

 2.2.1 JavaScriptオブジェクトの状態管理

 2.2.2 オブジェクトを値として扱う

 2.2.3 可動部分をディープフリーズ(再帰的にフリーズ)

 2.2.4 レンズを使ってオブジェクトグラフを操作

2.3 関数

 2.3.1 第一級オブジェクトとしての関数

 2.3.2 高階関数

 2.3.3 関数呼び出しの方法

 2.3.4 関数メソッド

2.4 クロージャとスコープ

 2.4.1 グローバルスコープの問題

 2.4.2 JavaScriptの関数スコープ

 2.4.3 疑似的なブロックスコープ

 2.4.4 クロージャの実践的な利用方法

2.5 まとめ

 

■Part 2 関数型のデザインとコーディング

第3章 データ構造の数を減らし、操作の数を増やす

3.1 アプリケーションの制御フローを理解する

3.2 メソッドチェーン

3.3 関数チェーン

 3.3.1 ラムダ式を理解する

 3.3.2 データを_.mapを使って変換する

 3.3.3 _.reduceを使って結果を集める

 3.3.4 _.filterを使って不要な要素を除去する

3.4 コードを把握する

 3.4.1 宣言型および遅延関数チェーン

 3.4.2 SQLライクなデータ:関数としてのデータ

3.5 再帰的に考えることを学ぶ

 3.5.1 再帰とは何か

 3.5.2 再帰的に考えるということ

 3.5.3 再帰的に定義されるデータ構造

3.6 まとめ

 

第4章 モジュール化によるコードの再利用

4.1 メソッドチェーンと関数パイプライン

 4.1.1 メソッドをまとめてチェーンにする

 4.1.2 関数をパイプライン状に配置する

4.2 互換性のある関数のための要件

 4.2.1 型互換の関数

 4.2.2 関数とアリティ:タプルの場合

4.3 カリー化された関数評価

 4.3.1 関数ファクトリをエミュレートする

 4.3.2 再利用可能な関数テンプレートを実装する

4.4 部分適用とパラメータ束縛

 4.4.1 コア言語を拡張する

 4.4.2 遅延関数に束縛する

4.5 関数パイプラインを合成する

 4.5.1 HTMLウィジェットとの合成を理解する

 4.5.2 関数合成:記述を評価から分離する

 4.5.3 関数ライブラリによる合成

 4.5.4 純粋なコードと不純なコードを取り扱う

 4.5.5 ポイントフリープログラミングの紹介

4.6 関数コンビネータを使ってフロー制御を管理する

 4.6.1 identity(Iコンビネータ

 4.6.2 tap(Kコンビネータ

 4.6.3 alternation(ORコンビネータ

 4.6.4 sequence(Sコンビネータ

 4.6.5 fork(join)コンビネータ

4.7 まとめ

 

第5章 複雑性を抑えるデザインパターン

5.1 命令型エラー処理の欠点

 5.1.1 try-catchによるエラー処理

 5.1.2 関数型プログラムで例外を投げない理由

 5.1.3 nullチェックの問題

5.2 より優れたソリューション:ファンクター

 5.2.1 安全ではない値のラッピング

 5.2.2 ファンクターの詳細

5.3 モナドを使った関数型エラー処理

 5.3.1 モナド:制御フローからデータフローへ

 5.3.2 MaybeモナドとEitherモナドによるエラー処理

 5.3.3 IOモナドを使用して外部リソースとやり取りする

5.4 モナドチェーンと合成

5.5 まとめ

 

■Part 3 関数型のスキルを磨く

第6章 関数型コードのテスト

6.1 ユニットテストへの関数型プログラミングの影響

6.2 命令型プログラムのテストにおける課題

 6.2.1 単純なタスクを特定して分解することの困難さ

 6.2.2 共有リソースへの依存は不一致な結果をもたらす

 6.2.3 あらかじめ定義された実行の順序

6.3 関数型コードをテストする

 6.3.1 関数をブラックボックスとして扱う

 6.3.2 制御フローではなくビジネスロジックに注目する

 6.3.3 モナドの分離を用いて純粋なコードを不純なコードから分離する

 6.3.4 外部依存性をモックする

6.4 プロパティベースのテストを利用して仕様を把握する

6.5 コードカバレッジにより有効性を測定する

 6.5.1 関数型コードのテストに関する有効性を測定する

 6.5.2 関数型コードの複雑度を測定する

6.6 まとめ

 

第7章 関数型コードの最適化

7.1 関数実行の中身を調べる

 7.1.1 カリー化と関数コンテキストスタック

 7.1.2 再帰コードの問題点

7.2 遅延評価を使用して実行を遅らせる

 7.2.1 alternation関数コンビネータ(OR)により不要な計算を避ける

 7.2.2 ショートカットフュージョンを利用する

7.3 "必要に応じて呼び出す"戦略を実現する

 7.3.1 メモ化を理解する

 7.3.2 計算が集中する関数をメモ化する

 7.3.3 カリー化とメモ化を利用する

 7.3.4 メモ化を最大限に利用するために分解を行う

 7.3.5 メモ化を再帰呼び出しに利用する

7.4 再帰と末尾呼び出し最適化(TCO

 7.4.1 非末尾呼び出しを末尾呼び出しに変換する

7.5 まとめ

 

第8章 非同期イベント/データのための関数型手法

8.1 非同期コードの課題

 8.1.1 関数間の時間的な依存関係

 8.1.2 コールバックピラミッドに陥る

 8.1.3 継続私スタイルを使う

8.2 Promiseによる第一級非同期処理

 8.2.1 thenメソッドチェーン

 8.2.2 同期処理と非同期処理の合成

8.3 遅延データ生成

 8.3.1 ジェネレータと再帰

 8.3.2 イテレータプロトコル

8.4 RxJSによる関数型プログラミングとリアクティブプログラミング

 8.4.1 オブザーバブルなシークエンスとしてのデータ

 8.4.2 関数型プログラミングとリアクティブプログラミング

 8.4.3 RxJSとPromise

8.5 まとめ

 

付録A 本書で使用したJavaScriptライブラリ

A.1 関数型JavaScriptライブラリ

A.2 本書で使用したその他のライブラリ

 

索引

 

出版社情報

正誤表など

 

book.impress.co.jp

 

著者紹介

Luis Atencio(ルイス・アテンシオ)

 

仮想化ソフトウェアベンダーのシトリックスシステムズに所属するソフトウェア開発エンジニア。コンピュータサイエンス分野で学士号と修士号を取得。

現在はJavaScriptJavaPHPのアプリケーション開発/設計にフルタイムで従事。技術コミュニティに積極的に参加、ローカルのイベントではプレゼン発表も行う。

ソフトウェアエンジニアリングについてのブログ(luisatencio.net)を公開。

Twitterアカウントは@luijar

 

twitter.com

 

書評

本書は、英語版「Functional Programming in Javascript」の日本語訳です。

 

Functional Programming in Javascript

Functional Programming in Javascript

 

 

JavaScriptでも、関数型プログラミングを使う機会が増えつつあるのではないか?と思います。

本書は、「Lodash」「Ramda」「RxJS」などのJSライブラリーを利用して、JavaScriptにおける関数型プログラミングの使いどころを理解するために役立つ本だと思いました。

 

関数型プログラミングの基礎 JavaScriptを使って学ぶ」という本とは、やや趣が違う本でしょう。

 

jsstudy.hatenablog.com

 

(1) 関数型プログラミングそのもの → 「関数型プログラミングの基礎 JavaScriptを使って学ぶ」で、丁寧に解説されています。

(2) 関数型プログラミングの使いどころ → 「JavaScript関数型プログラミング 複雑性を抑える発想と実践法を学ぶ」で、さらに知識を肉付けすることができます。

 

両方読んでみると、関数型プログラミングについて、別の角度から理解が深まります。

 

斜め読みメモ

パッと見で、気になったところをメモ。

 

(p.v)

本書の対象読者

 本書は、オブジェクト指向の基礎知識を有し、最新のWebアプリケーションの課題に対して一般的な認識を持つJavaScript開発者を対象としています。JavaScriptは幅広く利用できる言語であり、関数型プログラミングの入門書を探していて、日頃から慣れ親しんだ構文を利用したいと考えているなら、Haskellを学習する代わりに、本書を最大限に活用することができます(ただし、Haskellの学習に役立てようと考えているのであれば、本書は最適な情報源ではありません。言語には、それぞれ独自性があるので、Haskellを直接学習して理解するのが最短の近道です)。

 本書は、初級および中級の開発者が、高階関数クロージャ、カリー化、合成のほか、JavaScript ES6の新規機能であるラムダ式イテレータ、ジェネレータ、Promiseのスキルを高めるのに役立つでしょう。また、上級開発者向けには、モナドmonadリアクティブプログラミングまで広範囲な内容を網羅しています。イベント駆動や非同期のコードを書くという困難な仕事を乗り越えるために、JavaScriptプラットフォームを最大限に活用しながら、このような革新的な方法で立ち向かうことができます。

 

Haskellも学びましたが、すぐに使う場面がなくて持て余していました。

しかし、JavaScriptなら出番が多いので、無駄にならないところが嬉しいかも!?

 

コールバックをスッキリさせる

第8章の「非同期イベント/データのための関数型手法」をチェックして、すぐに活用できそうなら、本書は「買い」でしょう!

(逆にいえば、…すぐに使う予定のない知識だったら、読む必要性は低いかも?)

 

(p.271) 第8章 非同期イベント/データのための関数型手法

[本章のテーマ]

・非同期のコードを書く際の課題の明確化

関数型テクニックによりコールバックの入れ子を回避

・Promiseで非同期コードをストリーム化

・関数ジェネレータでデータを遅延生成

・リアクティブプログラミングの紹介

・イベント駆動型のコードにリアクティブプログラミングを使う

 

(p.272)

 クライアントサイドJavaScriptの世界では、他のどの環境よりも多くの難問に遭遇します。これらの難問は、巨大なクライアントコードの登場によるものです。そうしたコードは、従来のWebミドルウェアの利用による負担を(サーバと)分担することだけにとどまらず、「ユーザー入力の効果的な処理」「Ajaxなどを介したリモートサーバとの通信」「データの表示」などを一手に行う必要があります。本書では、これらの困難な状況の中でも高い保全性を維持するための最適なソリューションとして、関数型プログラミングを提案します。

 本章では、現実のJavaScriptプログラミングにおけるさまざまな課題への対処法として、関数型プログラミングを適用します。この対処法とは、プログラムがコードに沿って逐次に実行されない非同期データフローに関連するものです。ここで紹介する例にはAjaxやローカルストレージへのリクエストといったブラウザ機能も含まれています。目標は、ES6のPromiseを関数型プログラミングとともに活用すること、およびリアクティブプログラミングを導入することです。そうすることで、乱雑になりがちなコールバックのコードをエレガントで円滑な表現にします。

 

(参考) JavaScript ES6の「Promise」機能

Promiseについて0から勉強してみた - Qiita

JavaScript Promiseの本

 

「スマートコントラクト本格入門」という本で、「ブロックチェーン技術」や、仮想通貨「イーサリアム」の使い方を学んだ時、JavaScriptの実装「Truffle」でPromiseが使われていました。

 

スマートコントラクト本格入門―FinTechとブロックチェーンが作り出す近未来がわかる

スマートコントラクト本格入門―FinTechとブロックチェーンが作り出す近未来がわかる

 

 

関数型プログラミングは難しくない!?

jQueryを使ったことがあれば、関数型プログラミングも使えると思います。

 

(p.22)

 jQueryを書いたことがあれば、関数チェーンをたぶん何度か目にしているでしょう。チェーンとは関数を連続して呼出すものであり、それらの関数は共通のオブジェクト形式の戻り値を返します(jQueryの場合は$やjQueryオブジェクトが共通の戻り値に当たります)。 

 

リスト1.5 関数チェーンによるプログラミング

// _はLodashオブジェクト
_.chain(enrollment)
    .filter(student => student.enrolled > 1)
    .plunk('grate')
    .average()
    .value(); // -> 90 ※(1)

(1)value関数を呼び出すと、関数チェーンを実行する

 

(p.287)

jQueryでPromise

あなたがjQueryユーザーであれば、すでにPromiseを利用していると思います。jQueryの$.getJSON(およびすべての$.ajax呼び出しの派生メソッド)はjQuery独自のDeferredオブジェクトを返します。このオブジェクトはPromiseの非公式バージョンで、Promiseインターフェースとthenメソッドを実装しています。したがって、Promise.resolve()を使うと、

Promise.resolve($.getJSON('/students')).then(function () ...);

このオブジェクトはthenableとなり、Promise化されたオブジェクトと同じように使えます。

 

John Resigさんが作ったjQueryは、よく練られたライブラリーであり、広く使われてきました。

 

JavaScript Ninjaの極意

JavaScript Ninjaの極意

 

 

そのjQueryでも簡潔に書けなくなってしまった巨大なWebアプリのGUI作成には、関数型プログラミングが有用でしょう。

 

まとめ

  

「簡単にできることを複雑にやる必要はない」

という観点で、本書を参考にして、JavaScript関数型プログラミングを活用する方法を学んでみたいと思います。

 

(この本は読む人を選ぶと思うので、購入する際には実際に書店で中身を確認してから、必要な知識かどうか判断した方が良いと思います。)