2

これは、私が使用しようとしている「clx-user-callable.lisp」で定義されているマクロです。

(in-package :clx-gui)

(defmacro get-callback-wrapper (callback)
  (declare (ignorable callback))
  (let* ((func-name (gensym))
         (wrapper-name (intern (format nil "WRAPPER-~a" func-name) )))
    `(defun ,wrapper-name (caller-instance)
       (funcall ,callback) ;; User callbacks wont have arguments
       (closemenu caller-instance))))

私はこの方法でこのマクロを呼び出し、適切に動作します。

(in-package :clx-gui-test-app)

(create-user-menuitem "MyUserMenu" "MyEntryDialog"
                      (get-callback-wrapper 'my-callback))

(create-user-menuitem "MyUserMenu" "MyChoiceDialog"
                      (get-callback-wrapper 'my-callback2))

(create-user-menuitem "MyUserMenu" "MyMessageDialog"
                      (get-callback-wrapper 'my-callback3))

このようにマクロを使用するようにコードを変更すると、マクロを呼び出す関数にコールバックのシンボル名を渡すことによって、別のラッパー関数は返されず、常に同じラッパー関数が返されます。マクロを呼び出す関数は、マクロ定義と同じファイルおよびパッケージにあります。

(in-package :clx-gui-test-app)
(create-user-menuitem "MyUserMenu" "MyEntryDialog" 'my-callback)
(create-user-menuitem "MyUserMenu" "MyChoiceDialog" 'my-callback2)
(create-user-menuitem "MyUserMenu" "MyMessageDialog" 'my-callback3)

パッケージをマクロ定義に追加しようとしましたが、役に立ちません。

(wrapper-name (intern (format nil "WRAPPER-~a" func-name)
                      (symbol-package callback) )))

私は間違って何をしていますか?

私は SBCL-1.0.57 と Slime を使用しています。

4

1 に答える 1

1
CL-USER>
(defparameter foo1 (gensym))
FOO1
CL-USER> 
foo1
#:G4619
CL-USER> 
(defparameter foo2 '#:G4619)
FOO2
CL-USER> 
foo2
#:G4619
CL-USER> 
(eq foo1 foo2)
NIL
CL-USER> 
~           

または別の楽しい運動:

(defmacro make-fun ()  
  `(defun ,(intern (format nil "WRAPPER-~a" (gensym))) ()
     'bar))

CL-USER> 
(make-fun)
WRAPPER-G4726
CL-USER> 
(make-fun)
WRAPPER-G4730
CL-USER> 
(make-fun)
WRAPPER-G4734
CL-USER> 
(make-fun)
WRAPPER-G4738
CL-USER> 
(defun WRAPPER-G4745 ()
  'foo)
WRAPPER-G4745
CL-USER> 
(make-fun)
WRAPPER-G4745
CL-USER> (wrapper-G4745)
BAR
CL-USER>

ああ、私たちはその関数を上書きしました!

ある種の接頭辞名でgensymを表記したい場合は、gensym呼び出しで(オプションの引数として)それを行います。しかし、これはすべて単なる演習です。b/c私はまだOP問題でラムダを使用します。

(IMO)より単純で、ニーズに合わせて機能する代替実装を次に示します。

(defun get-callback-wrapper (callback)
  (lambda (caller-instance)
    (funcall callback) 
    (closemenu caller-instance)))

これにより、あなたが求めていると思う字句クロージャが生成されます。

于 2012-07-06T03:33:13.530 に答える