Clojure:binding と遅延シーケンス
Clojure in Action読んでて、へえってなったのでメモ。
当然と言えば当然なのかもしれないけれど。
(def ^:dynamic *factor* 10) (defn multiply [x] (* x *factor*)) (map multiply [1 2 3]) (binding [*factor* 20] (map multiply [1 2 3]))
Clojure の var はbindingで束縛することができる。
しかし直感に反して上のどちらのmapも [10 20 30] を返す。
これはなぜかというと、mapのような関数は遅延シーケンスを返すからで、この遅延シーケンスは必要となるまで評価されない。そして評価が実際に行われたときはすでにbindingフォームの外であるので、 factor も元々の10に戻っている。
これを意図したようにするには
(binding [*factor* 20] (doall (map multiply [1 2 3])))
とする必要がある。
どうてきすこーぷ、気をつけよう。
なんかこれ同じようなことをDBでもやったような気がする。
DBのコネクションをラップしたマクロが用意されてて、そいつが返すのは遅延シーケンスだということに気づかず、コネクションを閉じる前に結果を現実化しなかったせいでDBから結果が返ってきてないように見えて慌てたような。
- 作者: Amit Rathore
- 出版社/メーカー: Manning Pubns Co
- 発売日: 2011/11/28
- メディア: ペーパーバック
- クリック: 24回
- この商品を含むブログ (2件) を見る