読書会(Javaによる関数型プログラミング)第1回議事録

[ 戻る ]


==============================================================
Java読書会BOF 「Javaによる関数型プログラミング」を読む会 第1回
==============================================================
.. csv-table:: 開催概要

   "日時","2016年9月24日 10:00 - 17:00"
   "場所","川崎市教育文化会館 第3会議室"
   "出席者(敬称略)","高橋(徹)、遠藤、高田、吉本, 平山, 加藤、井上、川内、青山、松永、小棚木、吉田、岩室(書記)"

著者紹介/訳者紹介/レビュア紹介
============================================================

* 厳密には「JavaSE」⇒「Java SE」
* 日本唯一 ⇒ てらだよしおさんが2人目のJava Championになった。

日本語版まえがき
============================================================

* p.v
    * 「対象としていたの」⇒「対象としていたのは」
    * J2SEは1.4までではなく5まで。

まえがき
============================================================

はじめに
============================================================

* 書籍WebページのURLミス。
    * ×「http://www.oreilly.co.jp/9784873117041」
    * ○「https://www.oreilly.co.jp/books/9784873117041/」

1章 Hello、ラムダ式!
============================================================

1.1 考え方を変える
------------------------------------------------------------

1.1.1 従来の方法
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1.1.2 より良い方法
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1.1.3 具体的な改善ポイント
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1.1.4 シンプルな場合を超えて
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1.1.5 もう一度、従来の方法
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

* 「プリミティブ型への執着」の意味がわからない。
* 「単一責任の原則を無視しています」の意味がわからない。
    * 「フィルタ」「割引」「総和」の処理がまとめてひとつになっているからと思われる。
* p.4 L.6 「20ドル以上の場合」⇒「20ドルを超える場合」

1.1.6 もう一度、より良い方法
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1.1.7 改善ポイント
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

* 「大幅に改善されました」と書かれているが:
    * 改善前が簡単な内容なので、より良くなったと思えない。
    * 抽象的過ぎてかえってわかりづらくなっていないか。
    * この例を見せられても挫折しそう。
* 「reduce」の意味がわかりにくい。⇒「集約」の意味。

1.1.8 ラムダ式が救う
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

* p.6 「開発者を開放する」⇒「開発者を【開放】する」

1.2 関数型のコードによる大きな利益
------------------------------------------------------------

* p.7 3つ目の「・」⇒「新しいリストを生成し」というのは正しいのか?
    * 考え方としては間違っていないが、厳密には正しくない。実際にListのオブジェクトが生成されるわけではない。

1.3 なぜ関数型で記述するのか
------------------------------------------------------------

1.3.1 強化されたイテレータ
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1.3.2 ポリシーの強制
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

* このような使い方が一番恩恵が高いのではないか。
* 従来だとテンプレートパターンで書いていたが、テンプレートパターンだと柔軟性が低い。

1.3.3 ポリシーの拡張
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1.3.4 混乱のないコンカレンシー
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1.3.5 物語を語る
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1.3.6 関心の分離
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1.3.7 評価を遅らせる
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1.3.8 テスト環境の向上
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

* Java8用ユニットテストフレームワークはあるか? ⇒ 宿題
    * JUnit5は対応しているが、まだ正式リリースされていない。
    * モックがlambda対応だと便利そう。

1.4 革命でなく、進化
------------------------------------------------------------

1.4.1 宣言的になる
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1.4.2 不変性を尊重する
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

* p.16 「Joshua Block」⇒「Joshua Bloc【h】」
* Arrays.asList() は不変ではない。
    * 配列をラップする Arrays.ArrayList が使われる。
    * set() は使えるが add() は使えない。Listインターフェースを持つ配列と考えると良い。

1.4.3 副作用を避ける
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1.4.4 文より式を優先する
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1.4.5 高階関数を使って設計する
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

* 「関数を生成する」とは?
    * 無名クラスの生成とほぼ同等と考えればよい。
    * 実際にはJVMによりいろいろな最適化がなされる。

1.5 簡単にするためのほんの少しの砂糖
------------------------------------------------------------

1.6 まとめ
------------------------------------------------------------

2章 コレクションの使用
============================================================

2.1 リストをイテレート
------------------------------------------------------------

* p.28 例2-7 「System.out.println」⇒「System.out【::】println」
    * インスタンスメソッドでもメソッド参照にすることが可能。

2.2 リストの変換
------------------------------------------------------------

* p.29 例2-9 「System.out.println」の前で改行すべき。
* 「forEachを使うと負け」

2.2.1 ラムダ式を使う
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

* 例2-9と例2-10で出力の表現形式が微妙に異なる。例2-8にいたっては出力されていない。
* map()の返り値はStreamであってCollectionではないのでは?
    * Javaの型のCollectionではなく、日本語のコレクション(集まり)では。
    * 原書のエラッタではCollectionではないと指摘されている。
* p.30 例2-11 forEachにおけるlambdaの引数名がnameなのは不適切では?
    * サンプルコードでは「count」になっている。

2.2.2 メソッド参照を使用
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

* p.31 例2-12 forEachの部分もメソッド参照にできるのではないのか?
* (同上) 出力形式が変わっていないか?

* p.31 以下はカギカッコでくくる必要がある。
    * メソッド参照はいつ使うべきかを参照してください。
    * ⇒ 「メソッド参照はいつ使うべきか」を参照してください。

* lamda式とメソッド参照はどちらが良いか?
    * IntelliJではメソッド参照に書き換え可能な場合は指摘してくれる。
    * String::toUpperCaseの場合は引数をレシーバにしてtoUpperCase()を呼び出すが、System.out::printlnの場合は引数として渡される。このような違いはわかりづらいのではないか。

2.3 要素の検索
------------------------------------------------------------

* stream処理の返り値に関する表記がばらばら(コレクションだったりStreamだったりイテレータだったり)だが、中間操作の返り値は全てStream。
* Streamは順序は維持されるか?
    * 順序付けされているStreamとされていないStreamがある。
    * parallelStreamでは基本的に維持されない。

2.4 ラムダ式の再利用
------------------------------------------------------------

* p.34 「ある文字で始まる名前だけを抽出します」⇒「ある文字で始まる名前の数を抽出します」

2.5 静的スコープとクロージャ
------------------------------------------------------------

2.5.1 ラムダ式における重複
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

2.5.2 静的スコープで重複排除
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

2.5.3 スコープを限定するようにリファクタリング
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

2.6 要素を1つ選択
------------------------------------------------------------

* p.41 例2-25 「A name starting with ...」の「A」は冠詞。
* やっぱり「プリミティブ型への執着」の意味がわからない。

2.7 コレクションを単一の値に集約 (reduce)
------------------------------------------------------------

* 例2-31 "Steve"は単位元ではないので、この例ではかまわないが、バグの要因になるのではないか。
* 引数が1つのreduceはどのように処理されるのか?
    * streamの要素が空のときはOptional.empty()、1つのときはそのまま、2つ以上のときに引数のlambdaが呼ばれる。
    * 引数の型はBinaryOperator<T>なので、処理結果の型をstreamの型と異なるものにはできない。
    * 処理結果の型を異なるものにする場合は3引数のreduce()を用いる。

2.8 要素の結合
------------------------------------------------------------

* p.47 例2-33 普通はこのような書き方はしないのではないか。よくある書き方の例を以下に示す::

    // https://twitter.com/quiver2k/status/779576208761643008
    
    String delim = "";
    for (String name : friends) {
      System.out.print(delim + name);
      delim = ", ";
    }

* p.48 例2-35 joining()をクラス名無しで使えるのか?
    Collectors を static imoprt していると思われる。

2.9 まとめ
------------------------------------------------------------

3章 文字列、コンパレータ、フィルタ
============================================================

3.1 文字列のイテレーション
------------------------------------------------------------

* p.52 「Integerのストリーム」⇒「IntStream」
* p.53 訳注 「char()」⇒「chars()」
* p.53 例3-3 サンプルコードによると、メソッド名は「printchars」⇒「printChar」
* p.54 例3-6 サンプルコードによると、メソッド名は「printchars」⇒「printChar」
* p.54 「filter()メソッドと、foreach()」⇒「filter()メソッドと、foreach()メソッド」

3.2 Comparatorインターフェースを実装
------------------------------------------------------------

3.2.1 コンパレータを使ったソート
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

* p.56 「生成」⇒「作成」の方がよいのでは。
* メソッド参照を使い過ぎるのはどうか?
    * sortedくらいなら問題はないのではないか。
    * コンパイラがいろいろやっているということは、人間がコンパイラのエミュレーションをしないと理解できない可能性がある。

3.2.2 コンパレータの再利用
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

* 次回は p.62 の先頭から。

(以上)


[ 戻る ]