首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么我们需要在Lisp中使用funcall?

为什么我们需要在Lisp中使用funcall?
EN

Stack Overflow用户
提问于 2012-03-16 07:07:44
回答 3查看 10.5K关注 0票数 24

为什么我们必须使用funcall来调用Common Lisp中的高阶函数?例如,为什么我们必须使用:

代码语言:javascript
复制
(defun foo (test-func args)
  (funcall test-func args))

而不是更简单的:

代码语言:javascript
复制
(defun bar (test-func args)
  (test-func args))

出于程序背景,我对此感到有点惊讶,因为我更习惯的语言(例如Python、C#)不需要区分。特别是,至少在源代码级别上,C#编译器将其转换为类似于func.invoke()的形式。

我看到的唯一问题是,这将意味着我们不能再调用全局函数test-func,因为它会被遮蔽,但这几乎不是问题。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-03-16 07:32:05

严格地说,不需要funcall,但是有一些Lisp (list-2实现,比如Common Lisp)分隔了函数名称空间的变量名称空间。List-1实现(例如Scheme)没有这样的区别。

更具体地说,在您的示例中,test-func位于变量名称空间中。

代码语言:javascript
复制
(defun foo (test-func args)
  (funcall test-func args))

因此,您需要一个在变量名称空间中实际搜索与此变量相关联的函数对象的构造。在Common Lisp中,这个结构是funcall

另请参见this answer

票数 23
EN

Stack Overflow用户

发布于 2012-03-16 07:32:23

大多数Lisp都有两个名称空间(函数和变量)。当名称作为S表达式中的第一个元素出现时,将在函数名称空间中查找,否则将在变量名称空间中查找。这使您可以命名变量,而不必担心它们是否会影响函数:因此,您可以将变量命名为list,而不必将其命名为lst

然而,这意味着当你在一个变量中存储一个函数时,你不能正常地调用它:

代码语言:javascript
复制
(setq list #'+) ; updates list in the variable namespace
(list 1 2 3) => (1 2 3) ; looks up list in the function namespace

因此需要使用funcallapply

代码语言:javascript
复制
(funcall list 1 2 3) => 6 ; looks up list in the variable namespace

(并不是所有的Lisp都有两个名称空间: Scheme就是一个只有一个名称空间的Lisp示例。)

票数 19
EN

Stack Overflow用户

发布于 2012-03-16 08:22:07

在Common Lisp中,每个符号都可以与它的symbol-functionsymbol-value等关联。在读取列表时,默认情况下,Common Lisp解释如下:

  • arg1作为一个函数,因此检索test-funcsymbol-function,这是未定义的--因此,函数bar不能将
  • arg2作为要处理的内容工作--因此函数foo检索D11eval>的D12,在您的示例中,恰好是一个函数

F214

票数 -2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9729549

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档