这是我在尝试使用的“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。
答案 0 :(得分: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问题中使用lambda。
这是一个更简单的替代实现(IMO),应该可以满足您的需求:
(defun get-callback-wrapper (callback)
(lambda (caller-instance)
(funcall callback)
(closemenu caller-instance)))
这会产生我认为你正在追求的词汇封闭。