概括
(function foo)
是一种特殊形式,返回一个函数对象。这里取回了名字foo
。我们用它来获取一个函数对象。
(funcall foo)
用于调用作为参数传递的函数 - 这里是 . 的变量值foo
。funcall = FUNction CALL = 调用函数。我们用它来调用函数对象。
细节
这是一个闭包,它将谓词应用于数字 n,如果正确,则返回 (list n),否则返回 nil:
(defun all-those (predicate)
(lambda (n)
(if (funcall predicate n) (list n))))
不,这不是关闭。all-those
返回一个闭包,但它本身不是一个。
? #'all-those
#<Compiled-function ALL-THOSE #x302000C9631F>
? (all-those #'evenp)
#<COMPILED-LEXICAL-CLOSURE (:INTERNAL ALL-THOSE) #x302000E5ECFF>
我知道我需要调用 funcall 将这个闭包变成一个函数。
闭包是一个函数对象。
? (functionp (all-those #'evenp))
T
注意:所有闭包也是函数对象。并非所有函数对象都是闭包。
闭包是一个函数和相关的变量绑定。它是一个函数对象。
请注意,匿名函数不一定是闭包。(function (lambda () ()))
不返回闭包,因为没有变量绑定。你可以说它是一个带有空绑定的闭包,但在 CL 中它不被称为闭包。
请注意,在标准 Common Lisp 中,无法确定函数对象是否实际上是闭包,也无法通过变量名访问其绑定。
我知道我需要调用 funcall 将这个闭包变成一个函数。
funcall
用于调用带有参数的函数对象(或将从符号的函数值中检索的函数对象)。
请记住,调用函数有多种方法:
调用一个命名的全局函数:(foo bar baz)
调用一个命名的词法函数: (foo bar bar)
通过符号调用命名的全局函数:(funcall 'foo bar baz)
从变量值调用函数对象:(funcall foo bar baz)
从函数名(词法或全局)调用函数对象:(funcall #'foo bar baz)
调用匿名函数对象:(funcall (function (lambda (foo) foo)) 'bar)
或(funcall #'(lambda (foo) foo) 'bar)
或(funcall (lambda (foo) foo) 'bar)
调用匿名函数:((lambda (foo) foo) 'bar)
然后APPLY
是类似于FUNCALL
但从列表中获取参数。
(apply #'+ 1 2 3 (list 4 5 6)) is similar to (funcall #'+ 1 2 3 4 5 6)
FUNCALL本身就是一个函数。将评估其所有参数形式。第一个参数需要计算为符号或函数对象。funcall
将调用函数对象(或使用参数从符号函数值中检索的函数对象。
FUNCTION是一个特殊的运算符。它是语法。它本身不是一个函数。FUNCTION
期望一个符号或一个 lambda 表达式作为它的子形式。表单返回一个FUNCTION
函数对象,对应于符号(来自全局函数或词法函数)或lambda 表达式。
? (defun foo (bar) (list bar 'baz))
FOO
? (function foo) ; a function object from the global function
#<Compiled-function FOO #x302000CC0D1F>
? #'foo ; the same, differently written
#<Compiled-function FOO #x302000CC0D1F>
? (funcall #'foo 42) ; calling the function object
(42 BAZ)
? (funcall 'foo 42) ; calling the symbol-function of the symbol
(42 BAZ)
? (funcall (symbol-function 'foo) 42) ; as above
(42 BAZ)
? (flet ((foo (arg) (list arg :foo))) ; a local lexical function
(list (foo 43) ; calling the local lexical function
(funcall #'foo 42) ; calling a function object,
; from the local lexical function
(funcall 'foo 41))) ; calling the symbol-function of the symbol
((43 :FOO) (42 :FOO) (41 BAZ))