programming in Scala: 斜め読みメモ
ちょっとひっかかったところのメモ集。あとでちゃんと読むために。
Scalaスケーラブルプログラミング[コンセプト&コーディング] (Programming in Scala)
- 作者: Martin Odersky,Lex Spoon、Bill Venners,羽生田栄一,長尾高弘
- 出版社/メーカー: インプレスジャパン
- 発売日: 2009/08/21
- メディア: 単行本
- 購入: 18人 クリック: 687回
- この商品を含むブログ (121件) を見る
4.3 シングルトンオブジェクト
クラスメソッドの置き場
7.3.5 for yeild構文
構文としては
for <節> yeild <本体>
となっている。
scala> val ar = Array("sfdsas", "fdsa") ar: Array[java.lang.String] = Array(sfdsas, fdsa) scala> "ar".length res19: Int = 2 ^ scala> for { str <- ar if str.length > 1 } yield str res22: Array[java.lang.String] = Array(sfdsas, fdsa) scala> val ks = for { str <- ar if str.length > 1 } yield str ks: Array[java.lang.String] = Array(sfdsas, fdsa) scala> val kks = for { str <- ar if str.length > 1 } yield str + "asf" kks: Array[java.lang.String] = Array(sfdsasasf, fdsaasf) scala> for { k <- kks} println(k) sfdsasasf fdsaasf
7.4.4 try式による例外処理:値の生成
scala> def f(): Int = try {return 1} finally { return 2 } f: ()Int scala> f() res0: Int = 2 scala> def g(): Int = try {1 } finally {2} g: ()Int scala> g() res1: Int = 1
というわけで、字面と結果がうまくマッチしないんで、finallyでは値を返すな、と。終了処理の副作用のみにトドメよとのお告げ。
8.7クロージャー
自由変数はvar(ミュータブル)でもかまわないらしい。変更が反映される。
scala> def sum (a: Int, b: Int, c: Int) = a + b + c + 2 sum: (Int,Int,Int)Int scala> def s2sum = sum (s: Int, 2, 3) s2sum: Int scala> s2sum res4: Int = 12 scala> s = 6 s: Int = 6 scala> s2sum res6: Int = 13
ただし、変数が変化していく場合、定義されたときのものが使われる
scala> def makef (more: Int) = (x: Int) => x + more makef: (Int)(Int) => Int scala> var m = 1 m: Int = 1 scala> val m1 = makef(m) m1: (Int) => Int =scala> m1(1) res7: Int = 2 scala> m = 2 m: Int = 2 scala> m1(1) res9: Int = 2 scala> val m2 = makef(m) m2: (Int) => Int = scala> m2(1) res10: Int = 3 scala> m = 3 m: Int = 3 scala> m2(1) res12: Int = 3 scala> m1(1) res13: Int = 2
8.8 連続パラメータ
要するに可変長引数のことだが、Arrayを直接渡すときには技が必要らしい
scala> def plll(args: String*) = for (arg <- args) println(arg) plll: (String*)Unit ^ scala> plll("aa", "aa") aa aa scala> val ar = Array("sfdsas", "fdsa") ar: Array[java.lang.String] = Array(sfdsas, fdsa) scala> plll(ar):7: error: type mismatch; found : Array[java.lang.String] required: String plll(ar) ^ scala> plll(ar: _*) sfdsas fdsa
8.9 tail recursion
Java VMの制限のためか、Scalaでは今のところ単純なケースしかoptimizeされないそうだ。
相互再帰のケースはダメだとか。
9.1 p.162のしっくりこないところ
_のプレースホルダーが使えるのはわかる。で、queryという自由変数を掴んだクロージャーだとどこが上手いのかよくわからん。
9.3 Curry化
プレースホルダを使えば、途中の関数も拾い出せる。アンダースコアは、離して書いてもいい。
scala> def cursum (x: Int)(y: Int) = x + y cursum: (Int)(Int)Int scala> val c1 = cursum(1)_ c1: (Int) => Int =scala> c1(2) res3: Int = 3 scala> def c1f(y:Int) = cursum(1)(y) c1f: (Int)Int scala> c1f(2) res4: Int = 3
9.4 loan patternを書ける
普通のカッコと中カッコ{ }の使い分けについては、あんまりピンと来ないが、loan patternを素直に書けるという話は覚えておきたい。
def withBroker(resource: ResourceType)(op: ResourceCluncher => Unit) { val cluncher = new ResourceCluncher(resource) try { op(cluncher) } finally { cluncher.close } } val file = new File("date.txt") withBroker(file) { cluncher => cluncher.println(new java.util.Date) }
上記の場合、withBrokerの2番目の引数を{ }で括っているのが味噌だというのだが、、、うーん。
9.5 名前渡しパラメータ
うーん、これ黒魔術ですかw
var assersionsEnabled = true def byNameAssert(predicate: => Boolean) = if (assertionsEnabled && ! predicate ) throw new AssertionError
def byNameAssert(predicate: () => Boolean) とすると、呼び出すときに byNameAssert(() => 3 < 5) という風になって() => が省略できないが、上記のようにすると省略できる、、、そうです(汗
12 trait
mix-inだということ
14 表明
assert()とensuring()が使える。事後の保証もできる。この章はテストツールの紹介になっている。
15ケースクラスとパターンマッチ
Erlangなどでいうところのガードの話とか、パターンマッチとか。結構複雑なので、当面は覚えないw 脳みその節約せねばw
21 暗黙の型変換
必要な部分だけ、既存のクラスを拡張したいときに、implicitを使う
24 抽出子(extractors)
パターンマッチした結果を使いたい場合。unapplyを持つオブジェクトを定義する。
30 アクターと並行プログラミング
やっと、30/33で並行処理が出てきた。この冷遇っぷりは何w
要するにJavaに並列処理のツールはあると、それに加えてアクターのモデルを提供してますよ、そこんとこだけ説明しますよ、というスタンスである。
アクター、すなわちデータの共有をせず、メッセージ交換で協調動作します。ということ
- アクターはstart()で起動できる
- '!'メソッドでメッセージを送る
- 部分関数を引数としてreceiveを呼び出してメッセージを受け取る
- 普通のJavaシステムでは数千個のスレッドしかもてないし、スレッド切り替えも重いので、スレッド切り替えを節約できるreactというメソッドもあるらしい
- receiveするアクターは、実際の処理は別のアクターに投げちゃって、自分はブロックせずに次のメッセージを待つ、というお作法
- イミュータブルなデータだけ取り扱えば、スレッドセーフは自明
31 parser combinator
パーサの書きかた。DSLご用達。あとでちゃんと読む。