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 |

2009-02-06

インターンされないシンボルとGENSYM (2)

| 04:34 | インターンされないシンボルとGENSYM (2) - わだばLisperになる を含むブックマーク はてなブックマーク - インターンされないシンボルとGENSYM (2) - わだばLisperになる

「インターンされないシンボルとGENSYM」についてkozimaさんとNANRIさんから興味深いコメント頂きました!

kozimaさん:

1=#:hoge は、xyzzy のソースでは使われてます。が、他では見かけませんね。そんなに問題になるような状況は思いつかないのですが……。

一応、(function-lambda-expression (macro-function 'my-dotimes)) でソースを取り出して分解していけば捕捉できなくもないでしょうが、さすがにそこまで気にすることはないんじゃないかと思いますし。

おお、xyzzyでそういう記述があるとは知りませんでした!

また、FUNCTION-LAMBDA-EXPRESSIONで取り出すということで、どうにかして取り出した場合の問題を考えてみたのですが、

(defmacro foo ()
  (let ((sym '#:foo))
    `(progn ',sym)))

(eq (foo) (foo))
;=> T

(defmacro foo2 ()
  (let ((g (gensym)))
    `(progn ',g)))

(eq (foo2) (foo2))
;=> nil

(defmacro foo3 ()
  (let ((sym (make-symbol "FOO")))
    `(progn ',sym)))

(eq (foo3) (foo3))
;=> nil

というところで、'#:fooは展開の度にシンボルを生成していないことで何らかの捕捉を引き起こす可能性が高くなるのかなと思えました。

無理矢理ですが、

(defmacro bar ()
  (let ((sym '#:bar))
    `(locally
         (declare (special ,sym))
       ',sym)))

(set (bar) 3)
(symbol-value (bar))
;=> 3

(defmacro bar2 ()
  (let ((sym (gensym)))
    `(locally
         (declare (special ,sym))
       ',sym)))

(set (bar2) 3)
(symbol-value (bar2))
;=> unbound error

(defmacro bar3 ()
  (let ((sym (make-symbol "BAR")))
    `(locally
         (declare (special ,sym))
       ',sym)))

(set (bar3) 3)
(symbol-value (bar3))
;=> unbound error

など。もっとまともな局面がありそうですが、これくらいしか思い付きませんでした(^^;

NANRIさん:

「#:」も「#=」もリーダーマクロなのでreadtableが変な風にいじられていたらダメなんでしょうが、これも気にし過ぎのような気がします。

なるほど、確かに!

(set-macro-character #\# nil)

等とすると

(progn '#:bar)

は、#なんてパッケージはない!というエラーになってしまいますが、GENSYMや、MAKE-SYMBOLは普通に動きます。

また、#:の定義を追い掛けてみたところSBCLでは、MAKE-SYMBOLを呼びだすものになっていました。

他の処理系では、どういう風に定義されているかは調べていないのですが、#:は、MAKE-SYMBOL+αのリーダーマクロと考えていてもそんなに問題はなさそうです。

そうなると、表示されてくる#:は、なんなのだということになりますが、

(setq *print-gensym* nil)

で消せるので、読み書きで統一感を持たせるためのものなのかもしれません。#()もそんな感じですね。

まとめ

'#:fooだと弱いかもしれませんが、MAKE-SYMBOLなら大丈夫なのかもしれません。

しかし、MAKE-SYMBOLだと入力が長くて面倒ですね。

ということで、みんな故郷のGENSYMに帰って行くのかもしれません(笑)

ゲスト



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