2008/07/08

[Common Lisp] lambda と書くのがめんどうなときに。{}

[] は CLSQL で使うから {} にしてみよう。

(set-macro-character
#\{
(lambda (stream char)
(declare (ignore char))
`(_ ,@(read-delimited-list #\} stream t))))

(set-macro-character #\} (get-macro-character #\)))
Stefil というテストフレームワークを使ったテスト
;;{} を使ったパターン
(deftest |test-{}| ()
(is (equal '((2) (3) (4)) (mapcar {list (1+ _)} '(1 2 3))))
(is (equal '(1 4 9) (mapcar {* _ _} '(1 2 3))))
(is (equal '((1 a "A") (2 b "B"))
(mapcar {list _z _y _x} '("A" "B") '(a b) '(1 2))))
(is (equal '(1 2 3)
(funcall {identity _rest} 1 2 3)))
(is (equal '(2 1 3 4)
(funcall {apply #'list _b _a _rest} 1 2 3 4)))
(is (equal "a"
(with-output-to-string (*standard-output*)
(funcall {princ _} #\a))))
(is (equal "abc"
(with-output-to-string (*standard-output*)
(funcall {(princ _x) (princ _y) (princ _z)} #\a #\b #\c)))))
;;{} を使わないパターン
(deftest |test-_| ()
(is (equal '((2) (3) (4)) (mapcar (_ list (1+ _x)) '(1 2 3))))
(is (equal '(1 4 9) (mapcar (_ * _x _x) '(1 2 3))))
(is (equal '((1 a "A") (2 b "B"))
(mapcar (_ list _z _y _x) '("A" "B") '(a b) '(1 2))))
(is (equal '(1 2 3)
(funcall (_ identity _rest) 1 2 3)))
(is (equal '(2 1 3 4)
(funcall (_ apply #'list _b _a _rest) 1 2 3 4)))
(is (equal "a"
(with-output-to-string (*standard-output*)
(funcall (_ princ _x) #\a))))
(is (equal "abc"
(with-output-to-string (*standard-output*)
(funcall (_ (princ _x) (princ _y) (princ _z)) #\a #\b #\c)))))
やっぱりマクロキャラクタを使った方がいいかな。マクロキャラクタの問題点はパッケージ内に閉じずグローバルだってとこ。だからこそ便利なんだろうけどね。

いや、そうなのかな? このマクロキャラクタと Forth の仕組みってよく似てるし、また考えてみよう。

0 件のコメント: