Hatena::Groupcadr

わだばLisperになる このページをアンテナに追加 RSSフィード

2004 | 12 |
2005 | 01 | 02 | 07 | 10 | 11 |
2006 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 11 |

2011-05-07

CLでSRFI-42

| 23:10 | CLでSRFI-42 - わだばLisperになる を含むブックマーク はてなブックマーク - CLでSRFI-42 - わだばLisperになる

必要だった、ということは全くなかったのですが、Scheme版LOOPマクロという評判のSRFI-42をCLに移植してみました。

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は最適化するので大丈夫なようですが。)