$shibayu36->blog;

エンジニアをしています。プログラミングや読書のことなどについて書いています。

Scalaスケーラブルプログラミングを再読した

最近ScalaやPlay Frameworkを触っていて、implicitを多用したコードや関数リテラルを使ったDSL的なコードなどが読めずに困ってきたので、もう一度Scalaスケーラブルプログラミングを読んだ。

Scalaスケーラブルプログラミング第3版

Scalaスケーラブルプログラミング第3版

前回読んだ時 はまだScalaの基本的な文法周りが面白かったけど、今回は8章 関数とクロージャ、21章 暗黙の型変換とパラメーター、26章 抽出子辺りが面白かった。

  • 8章 関数とクロージャや21章 暗黙の型変換とパラメーターを読むことで、フレームワークから提供されるDSLっぽいコードがどうやって作られているのかを理解することが出来た
  • 26章 抽出子を読むことで、val (a, b) = ("hoge", "fuga")でなぜaとbにそれぞれ代入できるのかや、パターンマッチでList(a, b, _*)でaとbになぜ束縛できるのかとかの中身を知ることが出来た

以前Scalaスケーラブルプログラミングを読んだ - $shibayu36->blog; で書いたとおり読みやすい本ではないのだけど、Scalaに慣れてきたら8章、21章あたりはきちっと読んでおくと良さそうと思った。あとは読めないコードが出てきたときにそれに関連する部分を読むとScalaに対する理解が深まりそう。

読書ノート

  • for (とfor {の違いはセミコロンの省略ができるかどうか 136
  • yieldはコレクションの再生成 138
  • アンダースコアはScalaではまったくわけのわからない値のためのプレースホルダとして使われる 142
  • 関数リテラルの省略形 157
  • 関数呼び出しの特殊な形態 164
    • 連続パラメーター
    • 名前付き引数
    • デフォルト値
  • 関数の部分適用を_でやるのって関数リテラルの省略形っぽい
  • http://www.ne.jp/asahi/hishidama/home/tech/scala/function.html#h_function_object
  • 複数引数の場合、_なしでカリー化できるのか? -> defで定義されたメソッドならできない
  • 引数が一つだけの場合、括弧を中括弧で書いても良いことになっているので、これを使って制御構造っぽく書くことができる 180
    • なので、withPrintWriter(file: File)(op: PrintWriter => Unit)みたいに、引数リストを分けることで、制御構造っぽくかける
  • withPrintWriter(file) { writer => … }
  • 名前渡しパラメータの役割 182
  • 空括弧メソッド 186
  • Scalaは定義のための名前空間を2つしか持たない 191
    • 値(フィールド、メソッド、パッケージ、シングルトンオブジェクト)
    • 型(クラス、トレイト)
  • Nothingはすべてのサブ型で、これがあることでthrowなどの返り値を定義できる 216
  • traitのextendsでミックスイン出来るクラスを制限できる 227
  • ミックスインは右から適用される 229
  • Scalaのimport文は 242
    • 任意の場所にかけて
    • パッケージもオブジェクトも参照できて
    • インポートメンバーの名前を変えたりできる
  • java.lang._、scala._、Predef._は暗黙にimportされている 244
  • 単なるprotected・privateは、自分と同じクラスの別インスタンスにアクセス可能だが、thisを付けると同一クラスであっても別インスタンスにはアクセスできなくなる。 246 http://www.ne.jp/asahi/hishidama/home/tech/scala/class.html#h_access_modifiers
  • クラスとコンパニオンオブジェクトはそれぞれがそれぞれの非公開メンバーにアクセスできる 249
  • package.scalaにパッケージオブジェクトを定義し、そのパッケージ全体からアクセス可能にできる 249
  • パターンマッチのいろんな書き方 268 http://qiita.com/techno-tanoC/items/3dd3ed63d161c53f2d89
  • シールドクラスでは、同じファイルで定義されているサブクラス以外は新しいサブクラスを追加できない。そのため、パターンマッチがすべて行われているか検出できる 279
  • new RationalTrait { クラス定義と同様の書き方 } で、無名クラスを作ってインスタンスを作れる 386
  • lazyキーワードを使うと、その変数が利用される時に初めて計算される 390
  • implicitの規則 410
    • マーキングルール:implicitによって修飾された定義だけが暗黙の型変換に使われる
    • スコープルール:挿入される暗黙の型変換は、単一の識別子としてスコープ内にあるか、変換のソース型やターゲット型として対応付けられていなければならない
    • 1度に1回ルール:暗黙の型変換は1度しか挿入されない
    • 明示的変換優先ルール:書かれたままの状態でコードが型チェックをパスするときには、暗黙の型変換は行われない
  • Map等に使われる->はscala.PredefのArrowAssocクラスのメソッドで、暗黙の型変換が使われている 416
  • 暗黙のパラメータでのimplicitの利用は、個別のパラメーターではなくパラメーターリスト全体に適用される 419
  • 暗黙の型変換がおかしかったら、デバッグのために型変換を明示的に書いてみると良い 427
  • 21章のimplicitの説明は必読。いろんなモジュールでimplicitを使いまくってるので、そのあたりのモジュールを読むのにこの辺の知識は必要そう
  • unapplyメソッドが定義されているオブジェクトは抽出子 533
  • unapplyはある一つのものを分解するメソッド
  • 26章の抽出子を学ぶと、val (a, b) = (“hoge”, “fuga”)でどうして変数束縛出来るのかとか、パターンマッチでなぜオブジェクトの中身を変数に束縛できるのかとかが理解できる