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 |

2010-09-11

ZetalispのPKG-BIND

| 23:47 | ZetalispのPKG-BIND - わだばLisperになる を含むブックマーク はてなブックマーク - ZetalispのPKG-BIND - わだばLisperになる

LispマシンのLISPであるZetalisp/Lisp machine lispには、PKG-BINDというのがあって

(PKG-BIND "FOO"
  (DEFUN FOO (N) N))

のように指定した範囲だけパッケージが指定できます。

パッケージの仕組みからして違うのでそもそもCLで再現できるのか分からないのですが、今日Twitterでやりとりをしている中でS式を一旦文字列にしてREAD-FROM-STRINGすれば良いかと思い

(DEFMACRO PKG-BIND (&WHOLE WHOLE PKG &BODY BODY)
  (LET ((PKG-BIND-PKG (PACKAGE-NAME (SYMBOL-PACKAGE (CAR WHOLE)))))
    `(LET ((*PACKAGE* (FIND-PACKAGE ,PKG)))
       (EVAL
        (READ-FROM-STRING
         ,(WRITE-TO-STRING 
           `(PROGN 
              (IMPORT (READ-FROM-STRING
                       ,(FORMAT NIL 
                                "~A::PKG-BIND"
                                PKG-BIND-PKG)))
              ,@BODY)))))))

みたいなものを作成しました。

ZetalispのPKG-BINDが入れ子にできるのかどうか不明なのですが、とりあえず入れ子に対応。

(DEFPACKAGE :FOO (:USE :CL))
(PKG-BIND :FOO
  (DEFUN FOO (N) N)

  (DEFPACKAGE :BAR (:USE :CL))
  (PKG-BIND :BAR
    (DEFUN BAR (N) N)

    (DEFPACKAGE :BAZ (:USE :CL))
    (PKG-BIND :BAZ
      (DEFUN BAZ (CL-USER::N) CL-USER::N))))

(LIST (FOO::FOO 8)
      (BAR::BAR 8)
      (BAZ::BAZ 8))
;⇒ (8 8 8)

EVALを使うので外部のレキシカルな変数は取り込めないのですが、この方法以外でインターンするシンボルを選り分けるのは、なかなか面倒なので、まあ、これで良いかなと妥協。

以前はボディを走査してシンボルのパッケージを書き換えるという方法を試してみていました。

書き方が悪かった所為で上手く行かなかったような気もするので、シンボルを操作する方法でも書いてみたいと思います。

ゲスト



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