我正在编写一个将名称绑定到返回lambda的表达式的简单宏,但由于常见的lisp具有不同的函数和值的名称空间,我需要funcall
它无论我是将其包裹在defun
还是defvar
中。
(defun foo () (lambda-returning-expr))
(defvar bar (lambda-returning-expr))
(funcall (foo)) ; evaluates correctly
(funcall bar) ; also evaluates
那么哪种方法更正确?或者更确切地说,哪个最受索撒者的青睐?
答案 0 :(得分:4)
(defun foo () (lambda-returning-expr))
(defvar bar (lambda-returning-expr))
两种情况都需要 funcall ,例如(funcall(foo))和(funcall bar),但是有一个(foo)涉及额外的函数调用,每次都会评估(lambda-returning-expr),因此你可以得到一个不同的每次都回来。
最近有一个类似的方案问题Differences between two similar definitions,其中讨论了其中一些问题。
答案 1 :(得分:2)
(funcall (foo))
不是老虎钳的选择,因为你做了两个函数调用而不是一个。如果你想创建一个全局函数,你可以使用它:
(setf (symbol-function 'foo) (lambda (x) x))
(foo 10) ; ==> 10
您也可以使用变量,但请记住defvar
仅确保变量绑定。
(defvar *test* 10)
*test* ; ==> 10
(defvar *test* (lambda (x) x))
*test* ; ==> 10 (not changed since it's already existing)
如果您希望始终将其设置为已评估的表达式,请使用defparameter
。
(defparameter *test* 10)
*test* ; ==> 10
(defparameter *test* (lambda (x) x))
*test* ; ==> #<FUNCTION :LAMBDA (X) X>
BTW:defvar
和defparameter
会产生特殊变量。请记住*earmuffs*
,这样您就不会因为动态范围而陷入奇怪的错误。