Posted 2017-05-07 15:23:16 GMT

Common Lispを利用する上で普段何気無く利用している cl-user だが、実は処理系毎にユーティリティの充実度等が結構違っている。

そこで、ホームパッケージである cl-user パッケージを処理系毎に観察してみよう。

今回は、LispWorks 7.0 を眺める。

LispWorksは様々なプラットフォームで稼動するのでプラットフォーム依存な所はあるのだが、 cl-user のが取り込んでいるパッケージは下記の通りで、 LISPWORKS ( lw )と HARLEQUIN-COMMON-LISP ( hcl )を取り込んでいる。

(package-use-list :cl-user) → (#<The COMMON-LISP package, 2/4 internal, 978/1024 external> #<The HARLEQUIN-COMMON-LISP package, 0/8 internal, 353/512 external> #<The LISPWORKS package, 0/4 internal, 224/256 external>)

defpackage した際に :use を省略するとデフォルトのパッケージが取り込まれるが、上記3つが :use されるのがLispWorksの標準。

ちなみに、Harlequin Common LispというのはLispWorksを元々作っていた会社がHarlequinということに由来する。

Harlequin社は、〜Worksという名前で製品を作ることが多かったが、元々は、Harlequin CLを中心とした開発環境がLispWorksということだったらしい。

lw パッケージと hcl パッケージの使い分けが判然としないが、 hcl パッケージの方がCLtL1時代からのユーティリティが多い気がするが、 lw と hcl を合せて600近くのシンボルがあるので、結構ごちゃごちゃしているなあという印象はある。

これらユーティリティで有名なところでは、 when-let 、 if-let 、 with-unique-names 、 rebinding 、 split-sequence 辺りだろうか。

with-unique-names は、 with-gensym で rebinding 、 once-only として知られているマクロだが結構見掛けることは多いかと思う。

split-sequence はQuicklispにもあるユーティリティと同名だが、LispWorksがオリジナルなのかもしれない(とはいえ微妙に仕様が違う)

また、オリジナルの loop にあったユーザー定義の構文がデフォルトで使えるので、

( define-loop-macro for ) ( define-loop-macro repeat ) ( define-loop-macro with ) (for i :from 0 :repeat 10 :collect i)

こんなこともできるし、さらにユーザーがデータ型の処理方法を任意に定義することもできる( defloop 等)

また、非常にどうでも良い所ではあるが、ユーティリティに定義されていることが多い true と false も用意されている。

( mapcar #'true ( repeat 20 :for i :from 1 :collect i ) ) ( mapcar #'false ( repeat 10 :for i :from 1 :collect i ) )

Common Lispには constantly があるので不要に思えるのだが、用意している処理系は結構ある。

結び

以前から、処理系ごとに cl-user を比較してみていたが、これまで資料は貯めていたものの何故か書いたことがなかった。

今後、暇潰しに他の処理系についても書いてみるつもりである。

■

