2010年9月8日水曜日

Common Lisp でC風switch その2

C風switchをgoを使わない形に書き直して見ました。

caseの実行する式の部分に、後続で処理するすべての式をぶち込んでいます。

今回は明示的にブロックを抜けない限り、最後に評価された値が返ります。

(defmacro switch-2 (val &body clauses)
(let ((break (gensym)))
`(block ,break
(macrolet ((break-switch ()
`(return-from ,',break nil)))
(case ,val
,@(maplist
#'(lambda (rest)
`(,(caar rest) ,@(loop :for i in rest
:append (cdr i))))
clauses))))))

;; example
(switch-2 2
(2 (print 2))
(3 (print 3) (break-switch))
(4 (print 4)))

loopマクロの箇所は、最初はmapcanで書いていたのですが、なぜか処理が止まったので書き換えました。 mapcanが破壊的関数なため、maplistで段階的にアクセスしているリストの構造(clausesの一部)を変更してしまっているのだろうと思っています。

mapcanの非破壊版くらい仕様に入れておいて欲しかったです。

0 件のコメント:

コメントを投稿