Posted 2021-12-24 19:14:45 GMT
Lisp一人 Advent Calendar 2021 25日目の記事です。
本アドベントカレンダー最終日ですが、特にどうということもなくLispネタを書いてゆきます。
開始前は、溜っていたネタを書いていくだけ、と考えていましたが、良く考えてみれば、記事にできないから溜ってしまったネタが多く、思いの外記事を作成するのに苦労してしまいました。
これだったらマイナーなテーマのアドベントカレンダーの方が楽だったかもしれません。
さて、今回は、λリストの&list-of
を紹介します。
&list-of
は、Common Lispには取り入れられなかったλリストなのですが、defmacro
でlet
のような束縛構文を作成する際に頻出するパタンである、変数および値一覧の取得に便利に使えるものです。
(destructuring-bind (&rest &list-of (vars vals))
'((a 0)
(b 1)
(c 2))
(list vars vals))
→ ((a b c) (0 1 2))
試してみたい方はいないと思いますが、昔に何故かxyzzy用に移植したものがCommon Lispでそのまま動くので一応Gistのリンクを貼っておきます。
これでdefmacro
を作成するとこんな風になります
(defpackage "25d76a1c-7e26-5d83-8b7f-2afe5af560c1"
(:use cl destructuring)
(:shadowing-import-from destructuring destructuring-bind &list-of)
(:shadow defmacro))(in-package "25d76a1c-7e26-5d83-8b7f-2afe5af560c1")
(cl:defmacro defmacro (name (&rest args) &body body)
(let ((op (gensym "op"))
(form (gensym "form"))
(env (gensym "env")))
`(eval-when (:compile-toplevel :load-toplevel :execute)
(setf (macro-function ',name)
(lambda (,form ,env)
(destructuring-bind (,op ,@args) ,form
(locally
(declare (ignore ,op ,env))
,@body)))))))
これで、let
的な構文を作成するのに&list-of
を使うと、このようにシンプルに書けます。
(defmacro mylet (&list-of (vars vals) &body body)
`(multiple-value-bind (,@vars) (values ,@vals)
,@body))
(mylet ((a 0)
(b 1)
(c 2))
(list a b c))
===>
(multiple-value-bind (a b c)
(values 0 1 2)
(list a b c))
→ (0 1 2)
今回は&list-of
についての誰得情報を書いてみました。
古えに使われていたλリストについては、Lispマシンマニュアルに詳しい解説があるので、興味のある方は眺めてみてはいかがでしょうか。
■
HTML generated by 3bmd in LispWorks 8.0.0