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 |

2007-09-17

.4

| 00:17 | .4 - わだばLisperになる を含むブックマーク はてなブックマーク - .4 - わだばLisperになる

今日は、普通な題材にしようということで、lw-compatの中から適当に探してみました。

お題は、with-unique-namesと、rebindingにしました。

作者は、色んな所で目にするので恐らく著名な、Pascal Costanza氏です。

lw-compat:

http://www.google.com/codesearch?hl=en&q=show:yZBDJzpf0IM:HkZCZvv6THQ:7NeZEGaEv28&sa=N&ct=rd&cs_p=http://ftp.debian.org/debian/pool/main/c/cl-lw-compat/cl-lw-compat_0.22.orig.tar.gz&cs_f=cl-lw-compat-0.22.orig/lw-compat.lisp&start=1

お題 1.

(defmacro with-unique-names (names &body body)
  "Returns a body of code with each specified name bound to a similar name."
  `(let ,(mapcar (lambda (name) `(,name (gensym ,(symbol-name name))))
                 names)
     ,@body))
  • 初見時の感想

これは、Paul Graham氏でお馴染のwith-gensymじゃないだろうか。

  • 再現(失敗)
(defmacro with-uniq-names (names &body body)
  `(let ,(mapcar (lambda(n) `(,n ,(gensym (symbol-name n))))
		 names)
     ,@body))
  • 失敗したところ

コンマの場所を間違えて、展開時にgensymが働いてしまっているのに気付かず、結構悩みました。

  • 感想 (思ったことをつらつらと)
    • 丁寧に、gensymに名前を付けるのが、Costanza流なのか、Lispworks流なのか。一応Lispworksで確認してみたら、Lispworksでは、このスタイルのようです。
    • 単数->name、複数->names系の変数名命名法
    • 「&bodyは使う」派

お題 2.

(defmacro rebinding (vars &body body)
  (loop for var in vars
        for name = (gensym (symbol-name var))
        collect `(,name ,var) into renames
        collect ``(,,var ,,name) into temps
        finally (return `(let ,renames
			   (with-unique-names ,vars
			     `(let (,,@temps)
				,,@body))))))
  • 初見時の感想

これは、多重評価防止で使うonce-onlyという名前でお馴染のマクロじゃないだろうか。

  • 再現:
(defmacro rebinding (vars &body body)
  (loop for var in vars
        for name = (gensym (symbol-name var))
        collect `(,name ,var) into renames
        collect ``(,,var ,,name) into temps
        finally (return `(let ,renames
			   (with-unique-names ,vars
			     `(let (,,@temps)
				,,@body))))))

感想:

  • あまり内容は理解していないけれど、字面通り再現できた。ややこしい。
  • 内部にwith-unique-namesが使用されていることもあって把握はしやすくなっている。
  • 色々あるonce-only的マクロのうちでも簡潔で分かりやすい記述だと思った。

脱線:

once-onlyについて調べてみたら、これはかなり昔からあるようでLispマシンのマニュアルにも乗っていました。

http://common-lisp.net/project/bknr/static/lmman/macros.xml#once-only