20

我对 defun 宏的工作原理感到困惑,因为

(defun x () "hello")

将创建函数 x,但符号 x 仍然是未绑定的。

如果我将一些 lambda 绑定到 x 那么 x 将有一个值,但它不会被解释器视为如下形式的函数:

(x)

我认为这与 defun 应该在全局环境中定义函数这一事实有关,但我不确定它究竟是什么意思。为什么我不能在当前环境中对其进行阴影处理?

如果某些 lambda 绑定到符号,是否有任何方法强制解释器将符号视为函数?例如:

(setq y (lambda () "I want to be a named function"))
(y)

PS:我正在使用 SBCL。

4

2 回答 2

22

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

DEFUN您可以在函数命名空间中使用、FLETLABELS其他一些函数来定义函数。

如果要获取函数对象作为值,请使用FUNCTION.

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

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

或更短:

#'foo    ->   #<the function foo>

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

如果要将函数作为值调用,则需要使用FUNCALLor 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。由于我们有两个不同的命名空间,我们可以将相同的名称用于两种不同的目的。

另请注意,在局部函数的情况下,不涉及符号。命名空间不一定与符号相关联。因此,对于局部变量,无法通过符号名称进行函数查找。

于 2012-06-26T18:21:07.387 回答
7

Common Lisp 为每个符号有多个槽,包括一个值槽和一个函数槽。当您使用语法(x)时,common lisp 会查找 的函数槽绑定x。如果要调用值绑定,请使用funcallapply

http://cl-cookbook.sourceforge.net/functions.html

于 2012-06-26T17:26:29.783 回答