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

.7

| 19:54 | .7  - わだばLisperになる を含むブックマーク はてなブックマーク - .7  - わだばLisperになる

今日は、Gaucheクックブックの「#?=を使ったデバグ」というのがなんとなく便利そうでだったので、自分なりに真似して作ってみました。

Gaucheクックブック/「#?=を使ったデバグ」

http://d.hatena.ne.jp/rui314/20070628/p1

(defmacro debug-print (obj &optional name (stream t))
  `(let ((hr "** ----------------------------------------")
	 (name (if ,name ,name 0)))
     (format ,stream "~A~%** Debug: #~A | ~A => ~A | ~S~%~0@*~A~%" 
	     hr name ',obj ,obj (type-of ,obj))
     ,obj))

(defun gauche-debug-print ()
  (when (get-dispatch-macro-character #\# #\?)
    (or (yes-or-no-p "#?は既に使用されています。上書きしますか?") 
	(return-from gauche-debug-print)))
  (set-dispatch-macro-character #\# #\?
   (lambda (stream char arg)
     (declare (ignore char))
     (if (char= #\= (peek-char t stream))
	 (read-char stream))
     (list 'debug-print (read stream t nil t) arg t))))
(gauche-debug-print)

を評価すると、#?=が使えるようになります。

(let ((foo '(1 2 3 4 5))
      (bar "qwerasdfzxcv"))
  (nreconc foo (map 'list (lambda (x) #1068?=x)
		    #?=bar)))

のように使用し、


** ----------------------------------------
** Debug: #0 | BAR => qwerasdfzxcv | (SIMPLE-ARRAY CHARACTER (12))
** ----------------------------------------
** ----------------------------------------
** Debug: #1068 | X => q | STANDARD-CHAR
** ----------------------------------------
** ----------------------------------------
** Debug: #1068 | X => w | STANDARD-CHAR
** ----------------------------------------
   ~~~~~~ ~~~

のような結果を出力します。

ディスパッチングマクロ文字は10進数の引数が取れるようなのですが、捨てるのも勿体ないので使ってみました。

引数が無ければ、番号は0になります。

そして番号付けが面倒臭いので、emacsで現在のポイントの位置を挿入してみることにしました。

;; emacs lisp
(defun insert-gauche-debug-print-dispatch-char (insert-point-p)
  (interactive "P")
  (insert 
   (format "#%s?=" (if insert-point-p (int-to-string (point)) ""))))

C-U M-X insert-gauche-debug-print-dispatch-charで、数字を付けて#?=を挿入します。

.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

ゲスト



トラックバック - http://cadr.g.hatena.ne.jp/g000001/20070917