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-30

anaphoric-destructuring-bind

| 18:02 | anaphoric-destructuring-bind - わだばLisperになる を含むブックマーク はてなブックマーク - anaphoric-destructuring-bind - わだばLisperになる

quekさん作のwith-car/cdrは、非常にLISP2の特長が生かせた、自分のお気に入りのマクロの一つです。

(with-car/cdr '(1 2 3 4)
  (list car cdr))
;=> (1 (2 3 4))

この路線で行くところまで行くとすると、アナフォリックなdestructuring-bindだろう!、ということで色々考えていたのですが、こういう場合、symbol-macroletを使えば、簡単に作れる気がしたので作ってみました。

(eval-when (:compile-toplevel :load-toplevel :execute)
  (defvar *anaphoras*
    '(car cdr rest first second third forth fifth sixth seventh eighth ninth tenth)))

(defmacro anaphoric-destructuring-bind (list &body body)
  (let ((anaphoras (mapcar (lambda (x) `(,x (,x ,list))) *anaphoras*)))
    `(symbol-macrolet ,anaphoras
       ,@body)))

(let ((foo (list 1 2 3 4)))
  (anaphoric-destructuring-bind foo
    (list (car foo)
          (funcall #'car cdr)
          cdr
          first
          second
          (setq car 'alt)
          foo)))
;=> (1 2 (2 3 4) 1 2 ALT (ALT 2 3 4))

ClojureでL-99 (P12 ランレングス圧縮 その3)

| 13:13 | ClojureでL-99 (P12 ランレングス圧縮 その3) - わだばLisperになる を含むブックマーク はてなブックマーク - ClojureでL-99 (P12 ランレングス圧縮 その3) - わだばLisperになる

packの結果を加工せずに直接作成せよという問題。

Clojureのletは分割束縛の機能があるのでリスト分解 & 合成が楽です。

(defn 
  #^{:doc "P13 (**) Run-length encoding of a list (direct solution)."
     :test (do (test= (encode-direct []) [] )
               (test= (encode-direct [1]) [1] )
               (test= (encode-direct '(a a a a b c c a a d e e e e))
                      '((4 a) b (2 c) (2 a) d (4 e)))) }
; -------------
  encode-direct
; -------------
  ([coll]
     (if (empty? coll)
       []
       (loop [coll (concat coll (list (gensym))),
              tem (list 1 (gensym))
              acc [] ]
         (let [[car & cdr] coll, [cnt item] tem]
           (cond (empty? coll)
                 (rest (reverse acc))
                 ;; 
                 (= car item)
                 (recur cdr (list (+ 1 cnt) car) acc)
                 ;; 
                 :else
                 (recur cdr 
                        (list 1 car)
                        (cons (if (= 1 cnt)
                                item
                                tem)
                              acc))))))))