3

最初の照応マクロを書き込もうとしていますが、問題が発生しています。私はsblcとslimeを使用しています。

照応マクロが別のパッケージで展開されると、そのシンボルの前に、それが定義されたパッケージが付けられます(つまり、それらtjb-utilities::valueは単なる代わりになりvalueます。何が起こっているのでしょうか。

PE> (macroexpand-1 '(act-if-key :pcram (get-node) (print value)))
(IF (HAS-KEY? :PCRAM (GET-NODE))
    (LET ((TJB-UTILITIES::KEY :PCRAM)
          (TJB-UTILITIES::VALUE (GETHASH :PCRAM (GET-NODE))))
      (PRINT VALUE)))

これはマクロの定義です。

(defmacro act-if-key (key hashtable &body body)
  `(if (has-key? ,key ,hashtable) 
       (let ((key ,key) (value (gethash ,key ,hashtable)))
     ,@body)))

値のプレフィックスを付けると、正しく機能します。

(act-if-key :pcram (get-node) (print tjb-utilities::value))
; in: ACT-IF-KEY :PCRAM
;     (LET ((TJB-UTILITIES::KEY :PCRAM)
;           (TJB-UTILITIES::VALUE
;            (GETHASH :PCRAM (PHILOSOPHY-EXPERIENCE::GET-NODE))))
;       (PRINT TJB-UTILITIES::VALUE))
; 
; caught STYLE-WARNING:
;   The variable TJB-UTILITIES::KEY is defined but never used.
; 
; compilation unit finished
;   caught 1 STYLE-WARNING condition

"hello" 
"hello"

パッケージは次のように定義されています。

(defpackage #:tjb-utilities
  (:nicknames :tjb)
  (:use #:cl)
  (:export "HAS-KEY?" "KEY-VALUE-PAIRS" "ACT-IF-KEY" "TJB-MAKE-HASH-TABLE"))

(defpackage #:my-package
  (:nicknames :pe)
  (:use #:cl #:clsql #:tjb-utilities))

更新:ラムダリストのキーをkey_inに変更しても効果はありません

(defmacro act-if-key (key_in hashtable &body body)
  `(if (has-key? ,key_in ,hashtable) 
       (let ((key ,key_in) (value (gethash ,key_in,hashtable)))
     ,@body)))
4

2 に答える 2

3

「キー」と「値」のシンボルをエクスポートするだけです。それがAnaphoraのやり方です:

(defpackage :anaphora
7     (:use :cl)
8     (:export
9      #:it
10     #:alet
11     #:slet
12     #:aif
13     #:aand
14     #:sor
15     #:awhen
16     #:aprog1
17     #:acase
18     #:aecase
...etc.

エクスポートすることに注意してください。

アナフォリック マクロのポイントは、マクロの呼び出し元によって明示的に定義されていないマクロの本体内の特定のシンボルを意図的にキャプチャすることです (これは定義に対する極端なスタンスであることを理解しています)。したがって、アナフォリック マクロを使用するすべての人にとって、そのマクロの環境 (本体) にどのシンボルが導入されているかを知る必要があります。つまり、これらのシンボル名が環境に追加されても驚くべきではありません。したがって、照応をエクスポートしても問題はないと思います。

于 2012-11-04T05:41:54.857 に答える
2
CL-USER> (in-package #:tjb)
#<PACKAGE "TJB-UTILITIES">
TJB> (defmacro act-if-key (key hashtable &body body)
       (let ((value (intern "VALUE")))
         `(if (has-key? ,key ,hashtable) 
              (let ((key ,key) (,value (gethash ,key ,hashtable)))
                ,@body))))
ACT-IF-KEY
TJB> (macroexpand-1 '(tjb:act-if-key :pcram (get-node) (print value)))
(IF (HAS-KEY? :PCRAM (GET-NODE))
    (LET ((KEY :PCRAM) (VALUE (GETHASH :PCRAM (GET-NODE))))
      (PRINT VALUE)))
T
TJB> (in-package #:cl-user)
#<PACKAGE "COMMON-LISP-USER">
CL-USER> (macroexpand-1 '(tjb:act-if-key :pcram (get-node) (print value)))
(IF (TJB-UTILITIES::HAS-KEY? :PCRAM (GET-NODE))
    (LET ((TJB-UTILITIES::KEY :PCRAM) (VALUE (GETHASH :PCRAM (GET-NODE))))
      (PRINT VALUE)))
T
CL-USER> 

必要なものをすべてコピーしたかどうかわかりません。また、「キー」をどのように使用するつもりだったのか、少しぼやけているのでvalue、マクロがパッケージで作成される方法でのみ行いました。使用されている。に同じものが必要かどうかは、自分で判断してくださいkey

上記valueは、現在のパッケージ内のシンボルを、gethash返されるものにバインドします。元のバージョンでは、マクロのユーザーによって提供されたので、マクロ内にkeyシンボルは必要ないと判断しました。それは値だけです。key

しかし、少し待ってください。おそらくもっと良い答えがあるでしょう。おそらくmake-symbol、インターンの代わりにそれをそのままにして、どうにかしてバインドすることができます。わからない。

于 2012-11-03T16:43:27.170 に答える