mapcan,尖锐的报价和闭包

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 ...

Jos*_*lor 5

对于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)

  • @Frank如果你感到困惑(你应该)因为`lambda`在没有尖括号的情况下工作,那是因为`(lambda ...)`是一个扩展为`(function(lambda ...))的宏. ,内部lambda形式不再是宏扩展的,因为它在特殊的`function`操作符的范围内. (2认同)