Fra*_*ank 4 closures common-lisp funcall
我有点新的CL和目前正在设法绕到我的头mapcan,#',funcall和关闭.这是一个闭包,它将一个谓词应用于数字n,如果正确,则返回(list n),否则nil:
(defun all-those (predicate)
(lambda (n)
(if (funcall predicate n) (list n))))
Run Code Online (Sandbox Code Playgroud)
我知道我需要调用funcall将此闭包转换为函数.这很好用:
> (funcall (all-those #'evenp) 8)
(8)
Run Code Online (Sandbox Code Playgroud)
现在我尝试将以后创建的函数作为参数传递给mapcan:
> (mapcan #'(funcall (all-those #'evenp)) '(1 2 3 4))
Run Code Online (Sandbox Code Playgroud)
我得到一个编译时错误: (FUNCALL (ALL-THOSE #'EVENP)) is not a legal function name.
但是如果我省略#'也可以funcall:
> (mapcan (all-those #'evenp) '(1 2 3 4))
(2 4)
Run Code Online (Sandbox Code Playgroud)
现在我很困惑.我的理解是,当使用mapcan跟随符号的函数绑定(*)时我需要使用尖括引用函数,并且我需要funcall在"关闭闭包"时调用.
它是因为#'并且funcall相互抵消了,或者为什么我必须在上面的例子中省略它们?提前感谢您的回复.
(*)我知道在这个例子中我没有一个可以遵循其功能绑定的符号.但是,如果我使用匿名函数,mapcan我仍然需要尖锐引用它:(mapcan #'(lambda ...
对于mapcar,funcall等,您需要传递函数对象或符号.如果传递符号,则符号的符号函数将用作函数.如果传递函数对象,则将其用作函数.
你的所有这些函数返回一个函数.这意味着(mapcan(所有那些......)......)很好.
尖锐的引号(#')只是函数形式的简写.也就是说,#'foo与(function foo)相同:
的价值功能是名在当前词法环境功能价值.
如果name是一个函数名,那么该名称的功能定义是由最里面的词法封闭的flet,labels或macrolet形式建立的,如果有的话.否则返回函数名的全局功能定义.
如果name是lambda表达式,则返回词法闭包.在同一组绑定的闭包可能不止一次产生的情况下,各种结果闭包可能是也可能不是eq.
所以,你只能使用#"或功能与功能名称.这意味着符号(例如,#'汽车)或lambda表达(例如,#'(lambda(x)x)).这意味着以下不起作用(或者甚至是真的有意义):
#'(funcall (all-those #'evenp))
Run Code Online (Sandbox Code Playgroud)
现在我很困惑.我的理解是,当使用mapcan跟随符号的函数绑定(*)时我需要使用函数来引用函数,并且我需要在"关闭闭包"时调用funcall.
mapcar等的文档说它的第一个参数是:
function ---一个函数的指示符,它必须使用与列表一样多的参数.
从词汇表:
功能标志 ñ.功能的指示符; 也就是说,一个表示函数的对象,它是以下之一:符号(表示在全局环境中由该符号命名的函数),或函数(表示自身).如果将符号用作函数指示符但是它没有作为函数的全局定义,或者它具有作为宏或特殊形式的全局定义,则后果是未定义的.另请参见扩展函数指示符.
因此,您可以将函数直接传递给mapcar,funcall等,这正是您所做的:
(mapcan (all-those …) …)
Run Code Online (Sandbox Code Playgroud)
你也可以这样做:
(mapcan (lambda (x) ...) ...)
(mapcan #'(lambda (x) ...) ...)
(mapcan 'car ...)
(mapcan #'car ...)
(mapcan (symbol-function 'car) ...)
Run Code Online (Sandbox Code Playgroud)