【问题标题】:Common Lisp mapcar ' vs #' [duplicate]Common Lisp mapcar ' vs #' [重复]
【发布时间】:2014-07-27 04:15:36
【问题描述】:

我在 Common Lisp 中使用 mapcar,并且我看到了在 + 前面使用 #' 和 ' 的示例,但它们似乎都做同样的事情。使用哪个重要吗?

CL-USER> (mapcar '+ '(1 2) '(2 3))
(3 5)
CL-USER> (mapcar #'+ '(1 2) '(2 3))
(3 5)

【问题讨论】:

  • 请看this question
  • 标记为重复的问题包括一堆关于读取宏的讨论(这很好,但比这里需要的要多一些)。简短的回答是mapcar 的文档说它需要一个function designator,词汇表说它是“一个符号(表示在全局环境中由该符号命名的函数),或者一个函数(表示它自己)。” '+ 给出符号,#'+ 给出函数。

标签: common-lisp


【解决方案1】:

它们通常可以互换,但不是一回事。 mapcar 采用 function designator - 一个指定 symbol-function 的符号或一个指定自身的函数 - 这将被强制转换为函数对象。 #'foo是扩展为(function foo)的读取器宏,通过在词法环境中查找foo的函数值返回一个函数对象,即最里面的fletlabels或全局函数定义.因此,无需采取任何措施来强制它。但是,如果您将带引号的符号与 mapcar 一起使用,它会被强制转换为使用 symbol-function 的函数,这不适用于非全局函数定义,因为在这种情况下不涉及 fboundp 符号。例如:

CL-USER> (flet ((frob (x) (1+ x)))
           (mapcar #'frob '(1 2 3)))
(2 3 4)
CL-USER> (flet ((frob (x) (1+ x)))
           (mapcar 'frob '(1 2 3)))
; Evaluation aborted on #<CCL::UNDEFINED-FUNCTION-CALL #x18AB7F1E>.

另外,when exactly the coercion happens, is implementation dependent,它对自我或相互重新定义代码有影响。

总的来说,现在使用#' 似乎更受欢迎,可能是因为感觉它更一致——在任何你想传递函数的地方使用#' 是一个简单的规则。我很少看到引用符号与 CL 中采用函数指示符的函数一起使用。然而,在其他方言中,尤其是像 Emacs Lisp 这样的旧方言或动态范围的方言,将带引号的符号传递给这些函数是很常见的。

【讨论】:

  • 说 mapcar 需要一些将被强制转换为函数的内容可能会产生误导——您可以将一个以 lambda 开头的列表,例如,(list 'lambda '(x) 'x) 强制转换为函数,但它不是功能指示符。函数指示符只是一个函数(指定它自己)或一个符号(指定它的symbol-function)。这不太可能造成很大的混淆,但coerce 可以做的不仅仅是从函数指示符中检索指定的函数。
  • @JoshuaTaylor (错误地删除了以前的评论。)感谢您的评论!我想让事情保持简单,并且不想通过强制来定义指示符,而是解释当mapcar 以这种方式调用时会发生什么,如链接的 HS 部分中所示。 coerce 是对的,但我也不想描述这个功能,这就是为什么我没有把强制这个词放在等宽中。无论如何,我编辑了答案以避免任何歧义。
猜你喜欢
  • 2013-08-10
  • 2015-06-04
  • 2017-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多