Common lisp 为什么我必须对另一个函数返回的所有函数进行函数化?

Common lisp 为什么我必须对另一个函数返回的所有函数进行函数化?,common-lisp,lisp-2,Common Lisp,Lisp 2,为什么这样不行 ( ((lambda () (lambda (x) (funcall #'1+ x)))) 2) ; yields Compile-time error: illegal function call 我遇到了这样的情况,后来发现一个funcall修复了它,即 (funcall ((lambda () (lambda (x) (funcall #'1+ x)))) 2) ; => 3 我很困惑,因为第一个应该可以工作,因为我实际上有一个我正在调用的函数,而不仅仅是一个可

为什么这样不行

( ((lambda () (lambda (x) (funcall #'1+ x)))) 2)
 ; yields Compile-time error: illegal function call
我遇到了这样的情况,后来发现一个
funcall
修复了它,即

(funcall ((lambda () (lambda (x) (funcall #'1+ x)))) 2) ; => 3

我很困惑,因为第一个应该可以工作,因为我实际上有一个我正在调用的函数,而不仅仅是一个可能属于任何名称空间的符号(即
(类型((lambda()#'1+))=>函数
)。我想这有点像你不需要
funcall
一个lambda,例如
((lambda(x)x):HI);=>:您好
。我缺少什么?

Common Lisp的语法要求,每当您希望通过以下类型的计算机形式调用函数时:

(f a1 a2 ... an)
列表的第一个元素
f
,必须是表示函数名的符号,或表示lambda表达式的列表,即(请参阅):

lambda表达式。一种列表,在某些上下文中可以用来代替函数名,通过直接描述函数的行为来表示函数,而不是通过引用已建立函数的名称来间接表示函数;它的名字来源于它的第一个元素是符号lambda

所以,这基本上意味着不能将任何返回函数作为值的表达式作为第一个元素。在这些情况下,必须使用
funcall

因此,在您的第二个示例中,
funcall
的第一个参数是
((lambda()(lambda(x)(funcall#'1+x)))
,这是一种正确的复合形式,其中列表的第一个元素是lambda表达式
(lambda()(lambda(x)(funcall#'1+x))
(应用于参数的空列表)

在第一个示例中,列表的第一个元素是一个返回函数的表达式,因此必须使用
funcall

Common Lisp对所有可以计算的内容都使用单词形式。 表格是

  • 类似于
    foo
  • 复合形式、列表,见下文
  • 或自评估对象(如数字、字符、数组、字符串等)
复合形式是

  • 一种特殊的形式
    (…)
  • 类似于
    (lambda(…)…)
  • 宏窗体
    (…)
  • 或函数形式
    (…)
上面是一组复合形式。ANSI Common Lisp规范无法添加新的表单类型或不同的语法。构成函数(如
EVAL
COMPILE
accept)的接口不可扩展

大概是

(((lambda (foo)
    (lambda (bar)
      (list foo bar)))
  1)
 2)
不是有效的公共Lisp。这在Common Lisp中没有意义:

( <not a lambda form,
   not a special operator,
   not a macro name
   and not a function name>
2)
( <a function form> 2)
很难弄清楚它是干什么的。基本上,这将是只写代码

你的问题

(funcall (my-func 2) 3)
为什么我必须对另一个函数返回的所有函数进行函数化

简短的回答是:因为语法不允许其他方式,在Common Lisp中。

我已经阅读了这篇文章,然后修改了下面的代码:

(defparameter *my-fun* 1)

(defun my-func (v0)   
  (setf (symbol-function '*my-fun*)
    (lambda (v1)
      (+ v0 v1)))   
   '*my-fun*)
并以这种方式调用它((my func 2)3),但它也报告“非法函数调用”。我认为我的代码符合lambda演算,但哪里错了呢


在我看来,(my func 2)返回符号*my_fun*,并且*my fun*的函数单元指向一个函数对象,所以((my func 2)3)=>(*my fun*3)=>((lambda(v1)(+2 v1))3)=>(+2 3)=>5

首先,你的定义相同:

(defparameter *my-fun* 1)

(defun my-func (v0)   
  (setf (symbol-function '*my-fun*)
    (lambda (v1)
      (+ v0 v1)))   
   '*my-fun*)
但是,使用funcall调用:

(funcall (my-func 2) 3)

哦,我明白了,非常感谢你。除了lambda形式之外,是否还有另一种结构被归类为“lambda表达式”?我遵循了手册,但从实际操作来看,它非常模糊。不,lambda表达式是以符号lambda开头的列表,语法正确。没有其他类型的lambda表达式。@MasterMastic的“lambda表达式”仅适用于
(lambda…
,但该语言也定义了,即您提到的汽车是lambda表达式的形式,例如,
((lambda(x)(+40x))2)=>42
。另外,请看一下这个问题有点不同,但大部分答案都是适用的,并且引用了hyperspec中有关为什么
((lambda(x)(+2x))40)=>42
有效的相关部分。