我对defun宏如何工作感到困惑,因为
(defun x () "hello")
将创建函数x,但符号x仍将是未绑定的。
如果我将一些lambda绑定到x,那么x将有一个值,但它不会被解释器视为函数,如下所示:
(x)
我认为这与defun应该在全球环境中定义功能这一事实有关,但我不确定它究竟意味着什么。为什么我不能在当前环境中影响它?
有没有办法强制解释器将符号视为函数,如果某个lambda绑定到它?例如:
(setq y (lambda () "I want to be a named function"))
(y)
P.S。:我正在使用SBCL。
答案 0 :(得分:22)
Common Lisp具有不同的函数和值命名空间。
您可以使用DEFUN
,FLET
,LABELS
和其他一些函数在函数名称空间中定义函数。
如果要将函数对象作为值,请使用FUNCTION
。
(defun foo (x) (1+ x))
(function foo) -> #<the function foo>
或更短:
#'foo -> #<the function foo>
如果要调用函数,则编写(foo 100)
。
如果您想将该函数作为值调用,则需要使用FUNCALL
或APPLY
:
(funcall #'foo 1)
你可以传递函数并调用它们:
(defun bar (f arg)
(funcall f arg arg))
(bar #'+ 2) -> 4
在DEFUN的情况下:
不是(setf (symbol-value 'FOO) (lambda ...))
。
更像(setf (symbol-function 'foo) (lambda ...))
。
请注意,这两个名称空间使您可以编写:
(defun foo (list)
(list list))
(foo '(1 2 3)) -> ((1 2 3))
内置函数LIST
和变量LIST
之间没有冲突。由于我们有两个不同的名称空间,我们可以使用相同的名称用于两个不同的目的。
另请注意,在本地函数的情况下,不涉及符号。名称空间不一定与符号相关联。因此,对于局部变量,不可能通过符号名称进行函数查找。
答案 1 :(得分:7)
Common Lisp为每个符号提供多个插槽,包括一个值槽和一个功能槽。当您使用语法(x)
时,常见的lisp会查找x
的函数槽绑定。如果要调用值绑定,请使用funcall
或apply
。