为什么我们必须使用funcall来调用Common Lisp中的高阶函数?例如,为什么我们必须使用:
(defun foo (test-func args)
(funcall test-func args))而不是更简单的:
(defun bar (test-func args)
(test-func args))出于程序背景,我对此感到有点惊讶,因为我更习惯的语言(例如Python、C#)不需要区分。特别是,至少在源代码级别上,C#编译器将其转换为类似于func.invoke()的形式。
我看到的唯一问题是,这将意味着我们不能再调用全局函数test-func,因为它会被遮蔽,但这几乎不是问题。
发布于 2012-03-16 07:32:05
严格地说,不需要funcall,但是有一些Lisp (list-2实现,比如Common Lisp)分隔了函数名称空间的变量名称空间。List-1实现(例如Scheme)没有这样的区别。
更具体地说,在您的示例中,test-func位于变量名称空间中。
(defun foo (test-func args)
(funcall test-func args))因此,您需要一个在变量名称空间中实际搜索与此变量相关联的函数对象的构造。在Common Lisp中,这个结构是funcall。
另请参见this answer。
发布于 2012-03-16 07:32:23
大多数Lisp都有两个名称空间(函数和变量)。当名称作为S表达式中的第一个元素出现时,将在函数名称空间中查找,否则将在变量名称空间中查找。这使您可以命名变量,而不必担心它们是否会影响函数:因此,您可以将变量命名为list,而不必将其命名为lst。
然而,这意味着当你在一个变量中存储一个函数时,你不能正常地调用它:
(setq list #'+) ; updates list in the variable namespace
(list 1 2 3) => (1 2 3) ; looks up list in the function namespace因此需要使用funcall和apply
(funcall list 1 2 3) => 6 ; looks up list in the variable namespace(并不是所有的Lisp都有两个名称空间: Scheme就是一个只有一个名称空间的Lisp示例。)
发布于 2012-03-16 08:22:07
在Common Lisp中,每个符号都可以与它的symbol-function和symbol-value等关联。在读取列表时,默认情况下,Common Lisp解释如下:
test-func的symbol-function,这是未定义的--因此,函数bar不能将foo检索D11eval>的D12,在您的示例中,恰好是一个函数F214
https://stackoverflow.com/questions/9729549
复制相似问题