#:g1: &list-of

Posted 2021-12-24 19:14:45 GMT

Lisp一人 Advent Calendar 2021 25日目の記事です。

本アドベントカレンダー最終日ですが、特にどうということもなくLispネタを書いてゆきます。
開始前は、溜っていたネタを書いていくだけ、と考えていましたが、良く考えてみれば、記事にできないから溜ってしまったネタが多く、思いの外記事を作成するのに苦労してしまいました。
これだったらマイナーなテーマのアドベントカレンダーの方が楽だったかもしれません。

さて、今回は、λリストの&list-ofを紹介します。
&list-ofは、Common Lispには取り入れられなかったλリストなのですが、defmacroletのような束縛構文を作成する際に頻出するパタンである、変数および値一覧の取得に便利に使えるものです。

(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

comments powered by Disqus