多値
算数パズルを解くとき等に便利なmultiple-value-bindとかmultiple-value-listとかの多値を扱うマクロや構文は、名前が長ったらしいのがちょっと嫌。
Arcなら短かい名前付いてそうだと思って調べてみた所、そもそも多値がない模様。残念。
Schemeにはreceiveという特殊構文があった。
Gauche ユーザリファレンス: 4.6 変数束縛
(define (divrem n m) (values (quotient n m) (remainder n m))) (receive (q r) (divrem 13 4) (list q r)) ⇒ (3 1) (receive all (divrem 13 4) all) ⇒ (3 1) (receive (q . rest) (divrem 13 4) (list q rest)) ⇒ (3 (1))
色んな形で受けられてこれは便利、と思ってマクロを書いてみようとするものの、3番目の例のように受け取れる書き方は簡単には書けそうにない。
最初に書いた、2番目の形まで対応したマクロ。
(defmacro receive (vars values-form &body body) (if (atom vars) `(let ((,vars (multiple-value-list ,values-form))) ,@body) `(multiple-value-bind ,vars ,values-form ,@body)))
とりあえずこれでいいやとしばらく使ってたのだけど、PCL読んでたら13章の最後に強力なマクロが。
(destructuring-bind (a b . c) '(1 2 3 4 5 6) (list a b c)) ⇒ (1 2 (3 4 5 6))
これなら簡単に
(defmacro recieve (vars (&rest values-form) &rest body) `(destructuring-bind ,vars (multiple-value-list ,values-form) ,@body)) (recieve (q . r) (floor 13 4) (list q r)) ⇒ (3 (1))
xyzzyにはこのマクロがないのだけれど、id:g000001さんが移植してくれていた。
http://coderepos.org/share/browser/lang/xyzzy/destructuring/site-lisp/destructuring-bind.l
素晴らしい。
しかしパッケージの扱いが良くわかず、importしようとして怒られる。あれこれ試してみたけど今日のところは諦め。
#+:xyzzy (require "destructuring-bind") (defmacro recieve (vars (&rest values-form) &rest body) `(#+:xyzzy destructuring:destructuring-bind #+:common-lisp destructuring-bind ,vars (multiple-value-list ,values-form) ,@body))
cmu_loop.lにあったリーダーマクロを使ってみた。
これは酷い。