CLでSRFI-42 — #:g1

Posted 2011-05-07 14:10:00 GMT

必要だった、ということは全くなかったのですが、Scheme版LOOPマクロという評判のSRFI-42をCLに移植してみました。
- srfi-42.
- (http://srfi.schemers.org/srfi-42/srfi-42.html)
SRFI-42は、define-syntaxで書かれていて、CLのDEFMACROとは違うのですが、Drai Sitaram氏のmacro by example(mbe)を使ってみたところ殆ど修正もなく移植完了。
-mbe
-mbe (ASDF化してgithubに置いてみたもの)
srfi-42だとこんな感じに書けます

(defun palindrome-p (list)
  (every?-ec (:parallel (:- nom list)
                        (:- rev (reverse list)))
             (equal nom rev)))

(palindrome-p '(1 2 3 2 1)) ;=> T

(defun flatten (list) (append-ec (:- e list) (if (listp e) (flatten e) (list e))))

(flatten '(1 2 3 (4 5 (6 (7 (8 (9 (((10((((((())))))))))))))))) ;=> (1 2 3 4 5 6 7 8 9 10)

(defun taxi-number (n) (list-ec (:- a 1 n) (:- b (+ a 1) n) (:- c (+ a 1) b) (:- d (+ c 1) b) (if (= (+ (expt a 3) (expt b 3)) (+ (expt c 3) (expt d 3)))) (list a b c d)))

(taxi-number 100) ;=> ((1 12 9 10) (2 16 9 15) (2 24 18 20) (2 34 15 33) (2 89 41 86) (3 36 27 30) (3 60 22 59) (4 32 18 30) (4 48 36 40) (4 68 30 66) (5 60 45 50) (5 76 48 69) (6 48 27 45) (6 72 54 60) (7 84 63 70) (8 53 29 50) (8 64 36 60) (8 96 72 80) (9 34 16 33) (9 58 22 57) (10 27 19 24) (10 80 45 75) (11 93 30 92) (12 40 31 33) (12 51 38 43) (12 96 54 90) (15 80 54 71) (17 39 26 36) (17 55 24 54) (17 76 38 73) (18 68 32 66) (20 54 38 48) (20 97 33 96) (23 94 63 84) (24 80 62 66) (24 98 63 89) (29 99 60 92) (30 67 51 58) (30 81 57 72) (34 78 52 72) (35 98 59 92) (42 69 56 61) (47 97 66 90) (50 96 59 93) (51 82 64 75))

オリジナルと違うところとしては、 (: i 10)のようなものはCLでは不可なので、 (:- i 10)のようにして回避しました。
また、えぐいところとしては、キーワードシンボルにマクロが定義されることになります;(:- i 10)もマクロだったり。
ちなみに実行は関数呼び出しの連発になるので通常のLOOPと比べると25倍位遅い(SBCL調べ)ようですが、この辺りを高速化するのも盆栽的に面白いかなと思っています。
また、繰り返しは再帰なのですが、末尾再帰を最適化しない処理系では厳しいかもしれません。(SBCLは最適化するので大丈夫なようですが。)

comments powered by Disqus