我对CL有点陌生,目前正尝试将自己的头缠在mapcan#'funcall和闭包周围。
这是一个闭包,它将谓词应用于数字n,如果正确,则返回(list n),否则返回nil:

(defun all-those (predicate)
  (lambda (n)
    (if (funcall predicate n) (list n))))

我知道我需要调用funcall才能将此闭包转换为函数。这工作正常:
>  (funcall (all-those #'evenp) 8)
(8)

现在,我尝试将由此创建的函数作为参数传递给mapcan:
>  (mapcan #'(funcall (all-those #'evenp)) '(1 2 3 4))

我收到一个编译时错误:(FUNCALL (ALL-THOSE #'EVENP)) is not a legal function name

但是如果我省略了#'funcall:,它就可以工作
>  (mapcan (all-those #'evenp) '(1 2 3 4))
(2 4)

现在我很困惑。据我了解,在使用mapcan跟随符号的函数绑定(bind)(*)时,我需要对函数进行加引号,并且在“关闭闭包”时需要调用funcall

是因为#'funcall互相抵消了,还是在上面的示例中为什么我必须忽略它们呢?预先感谢您的任何答复。

(*)我知道在此示例中,我实际上没有一个可以遵循功能绑定(bind)的符号。但是,如果我使用匿名函数和mapcan,我仍然需要对其加引号:(mapcan #'(lambda ...

最佳答案

要传递 mapcar funcall 等,您需要传递函数对象或符号。如果传递符号,则将符号的符号功能用作功能。如果传递函数对象,则将其用作函数。

您的所有这些函数将返回一个函数。这意味着(mapcan(所有这些…)…)很好。

引号(#')只是函数形式的简写。也就是说,#'foo (函数foo)相同:



因此,您只能将#'函数与函数名称一起使用。这意味着符号(例如#'car )或lambda表达式(例如#'(lambda(x)x))。这意味着以下操作不起作用(甚至说不通):

#'(funcall (all-those #'evenp))



mapcar, etc.,的文档说它的第一个参数是:



从词汇表:



因此,您可以将函数直接传递给 mapcar funcall 等,这正是您在执行的操作:
(mapcan (all-those …) …)

您还可以执行以下操作:
(mapcan (lambda (x) ...) ...)
(mapcan #'(lambda (x) ...) ...)
(mapcan 'car ...)
(mapcan #'car ...)
(mapcan (symbol-function 'car) ...)

10-04 14:40