Hatena::Groupcadr

わだばLisperになる このページをアンテナに追加 RSSフィード

2004 | 12 |
2005 | 01 | 02 | 07 | 10 | 11 |
2006 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 11 |

2009-10-28

KMRCLを眺める (1) let-when

| 23:09 | KMRCLを眺める (1) let-when - わだばLisperになる を含むブックマーク はてなブックマーク - KMRCLを眺める (1) let-when - わだばLisperになる

ぼーっとしているとブログを更新しないでいるうちに月日が過ぎていってしまうので、何か更新が簡単にできそうなネタはないかと考えたのですが、日頃自分が良く使っているKMRCLの関数/マクロのソースを拾い読みして考えたことを書き散らかしてみることにしました。

KMRCLとは、Kevin M. Rosenbergさんの便利ユーティリティ集です。

Kevin M. Rosenbergさんは、DebianのCommon Lisp系のパッケージのメンテナでもあるようで、Debian/UbuntuのCL回りが嫌に充実しているのもこの方のお蔭なのかもしれません。ありがたや。

let-when

今日は、macros.lispのlet-whenを眺めてみます。

使い方としては、

(LET-WHEN (I (PROBE-FILE "/etc/passwd"))
  I)
;=> #P"/etc/passwd"

こんな感じです。

マクロの中身は、こんな感じです。

(defmacro let-when ((var test-form) &body body)
  `(let ((,var ,test-form))
      (when ,var ,@body)))

つまり、乱暴に言ってしまうならば、

(LET ((X (....)))
  (WHEN X 
    ....))

と書くのが面倒臭いので一体化してみた、という感じです。

最近のLISP方言である、Arcのwhenlet、Clojureのwhen-letやPaul Graham氏で有名なアナフォリックマクロのaifも似たようなものです。

Clojureのwhen-letについては、作者さんがアナフォリックマクロが好きじゃないようで、aifのようなマクロが作りにくく(できない?)なっているのですが、Clojureにaifはないのかという質問にwhen-letを使ったら良いじゃないかと、どこかで答えていたのを読んだ記憶があります。

また関連するところとしては、その他KMRCLのようなユーティリティ集には往々にしてwhen-letというものがあり、

(LISPWORKS:WHEN-LET (I (PROBE-FILE "/etc/passwd"))
  I)
#P"/etc/passwd"

まったく同じものが殆どです。

なぜマクロにするのかを考える

LISPのようなマクロがある言語だと、頻出するパターンは今回のlet-whenのように纒められます。

面倒臭いのでマクロに纒めていると、いつの間にやら、そいういう風に考えるようになってしまいます。

マクロの乱用について

マクロについては、乱用されるとわけがわからなくなる、という話をよく耳にしますが、マクロが自然に使える言語でこういうことを言っている人も少ない気がするので単に食わず嫌いな気がしています。

単純に上のlet-whenのパターンをlet-whenという名前をつけて利用するか、名前を付けないで毎回このパターンを手書きするかの違いだけではないでしょうか。

また、LISPでは、乱用できる機能については大抵、偉大な先達が乱用の限りを尽しているので、自重する必要も意味も大してないのではないかと私は思います…。(LOOP、FORMAT、その他)

ゲスト



トラックバック - http://cadr.g.hatena.ne.jp/g000001/20091028