为什么defun与(setq <name> <lambda>)不一样?</lambda> </name>

时间:2012-06-26 17:21:58

标签: lisp common-lisp sbcl

我对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。

2 个答案:

答案 0 :(得分:22)

Common Lisp具有不同的函数和值命名空间。

您可以使用DEFUNFLETLABELS和其他一些函数在函数名称空间中定义函数。

如果要将函数对象作为值,请使用FUNCTION

(defun foo (x) (1+ x))

(function foo)   ->  #<the function foo>

或更短:

#'foo    ->   #<the function foo>

如果要调用函数,则编写(foo 100)

如果您想将该函数作为值调用,则需要使用FUNCALLAPPLY

(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的函数槽绑定。如果要调用值绑定,请使用funcallapply

请参阅http://cl-cookbook.sourceforge.net/functions.html