多値

算数パズルを解くとき等に便利な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にあったリーダーマクロを使ってみた。
これは酷い。