【发布时间】:2012-07-04 18:30:03
【问题描述】:
这是我尝试使用的“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。
【问题讨论】:
-
那是因为宏是在编译函数时展开的,而不是在调用时展开的。
-
用
(eval-when (:compile-toplevel :load-toplevel :execute)包装你的create-user-menuitem函数。 -
请注意,defun/gensym 方法不能保证创建唯一的函数名称,b/c 两个 gensym 可以不是 eq 并且具有相同的打印值。如果您只是想定义一个永远不会再次使用的唯一函数名称,并且您并不真正关心名称,为什么不直接使用 lambda?
-
@claytontstanley:为什么两个 gensyms 会有相同的打印值?
-
请注意,正如所写的那样,没有理由需要将其实现为宏。一个函数就可以了,b/c 你提供给它的唯一参数只是一个带引号的符号。
标签: common-lisp sbcl