読者です 読者をやめる 読者になる 読者になる

日曜プログラミング

休日趣味でやってるプログラミング関連記事をダラダラと

プログラミング Clojure p145 でのちょっとした疑問

Clojure

環境構築も終わってちまちまと読み進めてるが、p145 での count-head-pairs の作り方にちょっとした疑問があるのでグチ。

count-head-pairs を作るベースに count-runs を作る所まではかなり参考になるんだが、count-head-pairsでcount-runs呼び出すなら、

 (fn [coll] (count-runs 1 #(= % :h) coll))

と書くよりも

 (partial count-runs 1 #(= % :h))

が分り易いでしょと言ってるが、defvarを使いたいが為だとすると、そもそもなぜ contrib の defvar を使いたかったのかがこれまた良くわからない。

docstringを後ろに持ってきたいと言う仮定であれば別に defn でもこう書く事はできて

 (defn count-head-pairs
   "Count runs of two that are both heads"
  [coll]
  ((partial count-runs 2 #(= % :h)) coll))

そうするわざわざ partial を使わずとも普通に defn 内で関数を呼び出せばいいんじゃないのかと。

 (defn count-head-pairs
   "Count runs of two that are both heads"
   [coll]
   (count-runs 2 #(= % :h) coll))

何というかこのサンプルだと特に defvar と partial が出てくる必要性を感じなかった。

defvar はどっちかと言うと common lisp 由来だと思ってて、あちらでは関数と変数でそれぞれで見た目同一シンボルの count-head-pairs が存在可能だから defvar なるものがあるんだと納得してたのだが、Clojure ではシンボルで見た場合に関数と変数で同一シンボルでは存在できないから defvar を導入する意義が良くわからない。だから contrib になってるのかな。

partial の方に関してはどちらかと言うと可変長引数扱う場合には短く書けるのかなと言う気が。

  ((fn [& args] (apply + 1 args) 2 3 4)

と書くよりは

  ((partial + 1) 2 3 4)

と書く方がかなり短くなる。引数固定だと文字通り部分適用した述語をその場で作りたい時とかに使えばいいのかな。

余談:
見たまま編集だと中途半端にはてな記法とバッティングするのとそいつを解決する途中ではてなでのコード色付け記法を見つけたので編集モードをはてな記法モードに変更。