【読書会メモ】Scalaスケーラブルプログラミング第2版 Martin Odersky【９，１０章】

# 第９章　制御の抽象化
## 重複するコードの削減

### Page 170
>共通部分は関数本体であり、非共通部分は引数という形で与える必要がある
>高階関数(higher order functions)すなわちパラメーターとして関数をとる関数は、コードを凝縮して単純化するチャンスを増やしてくれる。

<高階関数と関数合成の違い>
引数に関数をとって関数内部で評価するのと、
例えば、関数の引数自体はf・g(x)のように関数ではない場合

<高階関数>
f(g, h, x)
合成できない場合でもいい
(a->b)-> (b->c)
=>a->c
合成できなければいけない

### Page 171
>一部の動的言語はともかく、Scalaではこのように実行時にコードをペーストすることはできない。ではどうすればよいのか
>値としてメソッド名を渡せないのなら、メソッドを呼び出してくれる関数値を渡せば同じ効果が得られる

### Page 172
>これは関数なので、型の中に=〉が含まれている

>filesEndingメソッドで使われている_.endsWith(_)という関数リテラルは、次のものと同じ意味である。
```
(fileName: String, query: String) => fileName.endsWith(query)
```
これは
```
(fileName, query) => fileName.endsWith(query)
```
とも書ける

>filesMatchingと queryの両方からqueryパラメーターを取り除くことができる。すると、リスト 91に示すようにコードは単純化される。
>コストに比べてメリットが少なく、そんなことなら最初の重複を認めた方がましだ。


### Page 173
>_.endsWith(_)や _.contains(_)などの関数リテラルは、自由変数をつかんでいないので、実行時にはクロージャーではない関数値を作る
どういうことか説明。


## 9.2　クライアントコードの単純化

>高階関数のもう 1つの重要な用途は、 API自体に高階関数を使ってクライアントコードを簡潔にすることである。
>そのよい例が、 Scalaのコレクション型が定義している特殊な用途のループメソッドである※1
これらの特殊なループメソッドは、List、 Set、 Mapで拡張されている Traversableトレイトで定義されている。第１７章を参照


### Page 174
>existsメソッドは、ある特殊な制御構造を表現している。 whileや forのようにScala言語に組み込まれている制御構文ではなく、Scalaライブラリーが提供している特殊用途のループ構文である
組み込みではなくライブラリー


## カリー化

### Page 175
>新しい制御構造を言語機能の拡張のように感じさせる方法を理解するには、まずカリー化(currying)と呼ばれる関数型プログラミングのテクニックを理解して使えるようになる必要がある。
カリー化と部分適用の違いを説明する

### Page 176
>curriedSumの「第 2関数」に当たる参照を手に入れる方法はある。次のように、部分適用関数式の中でプレースホルダー記法を使ってcurriedSumを使うのである。
_の使い方も実際に説明する

>println_ のように通常のメソッドでプレースホルダーを使っていた前章では、れなければならなかったが、ここではスペースを入れる必要はない。println_ curriedSum(1)_ はそうではないからである。


## 9.4 新しい制御構造を作る

### Page 177
>このメソッドを使うメリットは、操作終了時にフアイルをクローズするのがユーザーコードではなく、 withPrintWriterになるということだ。そのため、ファイルをクローズし忘れるということがなくなる。withPrintWriterのような制御構造を実装する関数力劇リソースをオープンして、関数にリソースを「貸し出す」ので、このようなテクニックを回―ンパターン(loan pattern)と呼ぶ。
ローンパターンという名前と思想を覚えておくこと。

### Page 178
>クライアントコードでのこうした関数の呼び出しを、組み込み制御構造の場合の見た日に近づけるには、引数リストを括弧(丸括弧)ではなく中括弧で囲むとよい。引数を１個だけ渡すメソッド呼び出しでは、引数を囲む括弧を中括弧に変えてもよいことになっている。
中括弧の使い方

>引数を1個渡すときに括弧ではなく中括弧を使いたいのは、クライアントプログラマーが中括弧の間に関数リテラルを書き込めるようにしたいからである。こうすると、実質はメソッド呼び出しなのだが、制御構造を使っている感じが強まる

>第 1引数のFileはカリー化によつて別の引数リストに押し込むことができる
カリー化の効果

### Page 179
>この新バージョンは、前のものと基本的に同じである。異なるのは、 2個のパラメーターから構成された1個のパラメーターリストではなく、それぞれ 1個のパラメーターから構成された2個のパラメーターリストをとるようになったことだ
ここがカリー化の本質


## 9.5 名前渡しパラメーター
>中括弧の中のコードが引数をとるという点で、 ifやwhileなどの組み込み制御構造とは異なる
このような場合に対応するために名前渡しパラメーターが提供されている

### Page 180
>myAssert(5 > 3) // () =>がないので動作しない
>() => Booleanではなく、 => Booleanにすれば名前渡しパラメーターになる

### Page 181

>それに対し、 byNameAssertの predicateパラメーターの型は => Booleanなので、byNameAssert(5 > 3)の括弧の中の式は、 byNameAssert呼び出しの前には評価されない。代わりに、 5>3を評価するapplyメソッドを持つ関数値が作られ、その関数値がbyNameAssertに渡される。



# 第１０章　合成と継承 Composition and lnheritance
## 10.1 2Dレイアウトライブラリ

### Page 182
この章を通じてElementという２Dレイアウトの例を元に説明されていく

### Page 183

## 抽象クラス
>合成演算子は、同じドメインの要素を結合して新しい要素を作るので、コンビネーター(combinator)と呼ばれることも多い。
自己準同型の射になっている構成（モノイド）

>abstract class Element
キーワードの付け方はJavaと同じ

### Page 184
>Javaとは異なり、 abstract修飾子はメソッド宣言では不要である(付けてもよい)。
注意
>contentsという抽象メソッドを宣言(declare)しているが、現在のところは具象メソッドを定義(define)していない
宣言と定義の違い


## 10.3 パラメーターなしメソッドの定義
>このようなパラメーターなしメソッド(parameterless methods)は、 Scalaでは頻繁に見られるものだ。
>それとは対照的に、 def height(): Intのように、空括弧イ寸きで定義されているメソッドは、空括弧メソッド(empty paren methods)と呼ぶ
パラメータなしメソッドと空括弧メソッドのキーワードを覚える

>パラメーターがなく、ミュータブルな状態へのアクセスがオブジェクトのフイールドの読み出しだけなら、パラメーターなしメソッドを使うべきだとされている
真似したい原則

### Page 185
>この方法は、「属性をフィールドとメソッドのどちらで実装するかによってクライアントコードが影響を受けてはならない」という統一形式アクセスの原則(uniform access principle)※
OOPの重鎮の一人、メイヤーが提唱。
若干説明する。

>違いは、フィールドアクセスの方がメソッド呼び出しよりもわずかながら速いことだけだ
>その反面、フィールドに変更すると、 1つ 1つのElementオブジェクトが必要とするメモリ容量が増える

>Javaのふるまいに対応するという問題がまだ残っている。 Javaは統一形式アクセスの原則を実装していないのである。 Javaでは、 String.length()であって、 string. lengthではない(一方、 array.lengthであって、 array.length()ではない)。言うまでもなく、これは非常に紛らわしい。

>パラメーターなしメソッドと空括弧メソッドは、相互にもう一方をオーバーライドできるのである
>引数をとらないあらゆる関数呼び出しでは、空括弧は省略可能になっている
Javaとは違うので注意

>呼び出されるメソッドがレシーバーオブジェクトのプロパティ以上のものを表す場合は、空括弧を書く方がよいとされている
前段と同じ、真似したい原則


### Page 186

## クラスの拡張

>クラス名の後ろにextends節を付ける
Javaと同じ

>extends節を省略すると、 Scalaコンパイラーは、暗黙のうちにscala.AnyRefを拡張しているものと見なす。これは、」 avaプラットフォームにおけるjava.lang.Obj ectクラスと同じものである。つまり、 Elementクラスは、暗黙のうちにAnyRefクラスを拡張している
AnyRefは覚えておこう。


### Page 187
>サブ型という言葉には、「スーパークラスの値が必要な場所では、サブクラスの値を使える」という意味が含まれている
サブ型は覚えよう

>ArrayElementが実際のプロジェクトで使われるものなら、防衛的に配列そのものではなく配タリのコピーを返すことを考えるとよい。
ちょっとしたTips


### Page 188
>図 10.1は、 ArrayElementと ArrayIString]が合成(composition)関係にあることも示している


## 10.5 メソッドとフイールドのオーバーライド
>Elementクラスでのオ由象メソッドというcontentsの定義を変更せずに、ArrayElementクラスではcontentsの実装をメソッドからフイールドに切り替えることができる


>このバージョンのArrayElementにおける(valとして定義されている)contentsフイールドは、 Elementクラスにおける(defで定義されている)ノドラメーターなしメソッドの contentsの実装として、まったく問題のないものである。
>一方、 Scalaでは、Javaとは異なり、同じクラスの中で同じ名前のフイールドとメソッドを定義することは禁止されている。たとえば、次のJavaクラスは問題なくコンパイラーを通る。
統一形式アクセスの原則の実装


### Page 189
>一般に、 Scalaは定義のための名前空間を2個しか持っていない(Javaは 4個ある)。
>●値(フイールド、メソッド、パッケージ、シングルトンオブジェクト)
>●型(クラス、トレイト)

>パラメーターなしメソッドをvalでオーバーライドできるようにするためであ


## 10.6 パラメーターフィールドの定義
>contsという名前は、 contentsというフィールド名と似ているが衝突しないものということで選ばれている。この部分は「臭いコード Jであり、どこかに不要な冗長性や繰り返しが含まれている兆候である
>単一のパラメーターフィールド(parametric fields)定義でパラメーターとフィールドを結合すれば取り除ける。

### Page 190
>クラスパラメーターのプレフイックスとしては、 varも使える。この場合、対応するフイールドは再代入可能になる。そして、他のクラスメンバーと同じように、これらのパラメーターフイールドには、 private、 protected※ 5、 overrideの修飾子を追加することもできる


## 10.7 スーパークラスコンストラクターの呼び出し

### Page 191
>スーパークラスコンストラクターを呼び出すには、渡したい引数をスーパークラス名の後ろに括弧で囲んで書けばよい。たとえば、 LineElementは、スーパークラスであるArrayElementの名前の後ろに括弧で囲んでArray(s)と書けば、 ArrayElementの基本コンストラクターにArray(s)を渡すことができる。


## 10.8 override修飾子の使い方
>Scalaでは、親クラスの具象メンバーをオーバーライドするすべてのメンバーにこの修飾子を付けなければならない。また、同じ名前の抽象メンバーを実装する場合、この修飾子はオプションとなるため、付けても付けなくてもよい

### Page 192
>「不測のオーバーライド」(accidental overrides)は、いわゆる「脆弱な基底クラス問題」(fragile base class)が姿を現す典型例であるこの問題は、クラス階層の基底クラス(本書では通常、スーパークラスと呼んでいる)に新しいメンバーを追加すると、クライアントコードが使えなくなるリスクが生じるというものである。

### Page 193
## 10.9 多相性と動的東縛

### Page 194
>メソッド呼び出しや式が動的東縛(ダイナミックバインディングとも言う : dynamic binding)されることを見落とすわけにはいかない。つまり、実際に呼び出されるメソッド実装は、変数や式の型ではなく、実行時のオブジェクトのクラスによって決まるのである

### Page 195
## 10.10 ファイナルメンバーの宣言
>メンバーにfinall多飾子を付けてファイナルメツッド(final methods)

>クラス宣言に final修飾子を付けて、ファイナリレクラス(final class)を宣言すればよい