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

第4回Smiley Hackathon(仮)に参加してみることにしました!

| 12:14 | 第4回Smiley Hackathon(仮)に参加してみることにしました! - わだばLisperになる を含むブックマーク はてなブックマーク - 第4回Smiley Hackathon(仮)に参加してみることにしました! - わだばLisperになる

以前から、Smiley Hackathon(仮)って面白そうだなと思っていたのですが、今回は参加してみることにしてみました。

自分は、前に作ったCLでMooseの続きを作ったりしたいと思っています。(会場がPerlな雰囲気なので)

まだ定員に10名位の余裕はあるようです。

折角なのでどなたか一緒にMooseマクロを作りませんか!

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

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

Common Lispでは、インターンされないシンボルは、#:fooのように書くことができて、これはリードの度に新しいシンボルになるので同名でも同じシンボルではありません。

そう考えると例えば、my-dotimesを定義するとして

(defmacro my-dotimes ((var times &optional result)
                      &body body)
  (let ((limit (gensym)))
    `(do ((,limit ,times)
          (,var 0 (1+ ,var)))
         ((<= ,limit ,var) ,result)
       ,@body)))

と書いているgensymは別に毎回違う名前を生成する必要はないんじゃないかと思えて来ました。

つまり

(defmacro my-dotimes ((var times &optional result)
                      &body body)
  (let ((limit '#:limit))
    `(do ((,limit ,times)
          (,var 0 (1+ ,var)))
         ((<= ,limit ,var) ,result)
       ,@body)))

で良いのではないかと。(make-symbol "LIMIT")でも良いでしょう。

更に、同じシンボルを指せれば良いので

(defmacro my-dotimes ((var times &optional result)
                      &body body)
  `(do ((#1=#:limit ,times)
        (,var 0 (1+ ,var)))
       ((<= #1# ,var) ,result)
     ,@body))

とも書けるでしょう。

展開結果は、

(let ((foo 10))
  (my-dotimes (i (incf foo) (progn 
                              (write i)
                              (terpri)))
    (write i)))

;; %=>
(DO ((#:LIMIT (INCF FOO))
     (I 0 (1+ I)))
    ((<= #:LIMIT I) (PROGN (WRITE I) (TERPRI)))
  (WRITE I))

のような感じです。

展開結果で、#:g0001等になるより読みやすく、(gensym "LIMIT")などとするより面倒でなく読みやすいという感じなのですが、#:fooの表記を使うと何か致命的な問題があったりするのでしょうか。

例えば、symbol-nameで判定してなにかすると、キャプチャできてまずい、とか。しかしその場合、GENSYMでも恐らく問題はありかなと。

CLより前は、#:という記法がなかったよう(少なくともMacLISPにはない様子)なので、GENSYMを利用する必要があります。

ちなみにGENSYMは同じ名前にすることができて

(gensym 100)
;=> #:G100

とすれば、いつでも#:G100が返りますが、当然ながらこれもEQになりません。

しかし、名前が被ろうが被るまいが、インターンされないシンボルはなんにしろ互いにEQになりません。

MacLISPの時代は、インターンされないシンボルを記述する一番手軽な方法は、GENSYMのようですが、GENSYMを利用する必要が無くなってもMacLISPから続く伝統がそのまま受け継がれていたりするのでしょうか。真相や如何に。

ゲスト



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