为什么禁止函数位置的函数对象(但允许lambda表单)?

Fra*_*ank 4 syntax lambda common-lisp

拉姆达形式在功能位置表达

函数位置的lambda表达式编译得很好:

> ((lambda (n) (> n 10)) 42)
T
Run Code Online (Sandbox Code Playgroud)

从函数位置的lambda构建的闭包

另一方面:

> (defun greater-than (x)
     (lambda (n) (> n x)))
GREATER-THAN

> ((greater-than 10) 42)
Compile-time error:  illegal function call
Run Code Online (Sandbox Code Playgroud)

不起作用.

(我显然需要打电话FUNCALL让它工作:(funcall (greater-than 10) 42)=> T.

为何选择此设计?

我理解为什么带有函数对象作为值绑定的SYMBOL 必须不起作用,例如:(let ((foo (lambda () 42))) (foo)).单独的命名空间和所有这些.

但为什么禁止功能对象本身在功能位置?这个决定背后的理由是什么?

Rai*_*wig 7

什么是lambda形式?

函数位置的lambda形式编译得很好:

在Common Lisp中,lambda表达式不是一种形式.具有lambda表达式和零个或多个参数的列表是一个表单,特别是一个lambda表单.可以评估表单,而不是lambda表达式.注意:还有一个宏运算符lambda,它使用特殊运算符宏表单 扩展(lambda ...)(function (lambda ...))- 这是一个有效的表单. function

(                       ; the whole list is a valid lambda form

 (lambda (n) (> n 10))   ; a lambda expression, not a form

 42)                     ; 42 is a form, too
Run Code Online (Sandbox Code Playgroud)

上面的lambda形式大致类似于:

(let ((n 42))
  (> n 10))
Run Code Online (Sandbox Code Playgroud)

在运行时调用评估结果的函数对象

但为什么禁止功能对象本身在功能位置?这个决定背后的理由是什么?

Common Lisp更喜欢在函数位置具有已知(或未知)的函数.

(sin 3)
((lambda (x) (sin 3)) 3)
(unknown-function 3)
Run Code Online (Sandbox Code Playgroud)

最重要的是,三个函数不能是其他函数:它们不能是数字,字符串或其他数据对象.没有办法在那里放置另一个数据对象.运营商如DEFUN,FLET和其他人拒绝定义功能,这是其他一些数据类型(数字,字符串,...).

如果我们在函数位置进行计算,我们可以写:

((if (> foo bar) 42 #'sin) 3)
Run Code Online (Sandbox Code Playgroud)

根据(> foo bar)对此的评估可能类似于(sin 3)或者(42 3),后者不是有效形式,因为数字不是函数.

Common Lisp的需要一个明确使用的一个FUNCALL,APPLY,MULTIPLE-VALUE-CALL调用函数对象.这使得在源代码中清楚地表明正在计算/检索和调用函数对象.他们还做了必要的检查,事实上传递的东西确实是一个函数或表示函数的符号.

背景

有关详细信息,请参阅Gabriel/Pitman的"功能单元和值单元中的分离技术问题".


Sva*_*nte 6

大多数情况下,"历史原因",即实现问题,但在功能和值命名空间的分离方面,它在语义上也不明显.操作员位置中的表单被评估为其功能值.只有符号具有函数值.

Lambda表格是一个特例; 您可以想象它们在函数和值命名空间中求值.然而,这实际上并不正确,只是近似/合理化.

当我年轻的时候,我想象应该有一个读取器宏镜像#',例如#^,这样你就可以将某些东西"拉"到函数命名空间中,就像你将某些东西"拉"到值命名空间中一样#'.但是,它只会扩展到funcall:

(#^(make-adder 5) 3)(funcall (make-adder 5) 3)

我现在非常不愿意为这种无聊的用途引入读者宏.放松,只需使用funcall,它最终确实非常好用.