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 |

2008-09-25

ClojureでL-99 (P08 リストの圧縮)

| 04:55 | ClojureでL-99 (P08 リストの圧縮) - わだばLisperになる を含むブックマーク はてなブックマーク - ClojureでL-99 (P08 リストの圧縮) - わだばLisperになる

今回は、letのリストの分割束縛機能を無理矢理気味に使ってみました。テストのところもなんとなくマクロに。

(defn 
  #^{:doc "P08 (**) Eliminate consecutive duplicates of list elements."
     :test (test= (compress '(a a a a b c c a a d e e e e))
                  '(a b c a d e))}
; --------
  compress [coll]
; -------- 
  (loop [coll coll, acc `[~(gensym)] ]
    (let [[head & tail] coll]
      (cond 
       (empty? coll) 
       (rest (reverse acc))
       ;; 
       (= head (first acc))
       (recur tail acc)
       ;; 
       :else 
       (recur tail (cons head acc))))))

(defmacro test= [expr val]
  `(do (assert (= ~expr ~val))))

Clojureでは、,(コンマ)ではなく、~でクオート解除になります。コンマは空白として扱われるので、変数束縛の部分等でみやすく清書するために使えます。

また、ClojureはLISP-1ということもあり、古典的なマクロでは、展開先で内部で使用している関数(マクロ)が書き換えられてしまう問題が心配されますが、これは回避してくれるとのこと。CLのように名前空間も分かれているので(CLのパッケージ的)この点でもScheme+古典的マクロより安全そうです。

(let [= list]
  (= 3 3))
;=> (3 3)

(defmacro foo [x]
  `(= ~x ~x))

(let [= list]
  (foo 3))
;=> true ; 意図した通りの動作

;; scheme (Gauche等)
(define-macro (foo x)
  `(= ,x ,x))

(let ((= list))
  (foo 3))
;=> (3 3) ; 書き換えられてしまいました。