这来自这个 CS 61A 关于 SICP 的注释 p80~82 关于 ucblogo(Logo 的方言,源自 Lisp):
第二,Logo具有一流的表现力;您可以运行一个作为参数获得的列表。
这似乎意味着数据隐式地可以成为“一流表达”的函数。这有点奇怪。
允许一流的表达式(WHILE)。
...
to while :condition :action if not run :condition [stop] run :action while :condition :action end to example :x while [:x > 0] [print :x make "x :x-1] end
这不适用于词法作用域,因为在过程中我们无法评估参数 表达式,因为变量 x 未绑定在词法上围绕 while 的任何环境中。动态的 作用域使 example 的局部变量可供 while 使用。这反过来又允许一流的表达。 (这就是 Logo 用来代替一流函数的方法。)
“变量 x 不受词法上围绕 while 的任何环境的约束”是由于将
[:x > 0]
作为引用的内容传递。就是下面说的
但是由于表达式不表示为列表,因此分隔列表的相同标点符号也会引用它:
2.1 一般特殊表格实现
如果你想在Scheme中写作, 基本上,你必须将其变成一种特殊的形式,使用 thunk 变成某种东西。也就是说,你会有 使
(while cond act)
变成
(while-helper (lambda () cond) (lambda () act))
但Logo的观点是,对于初学者来说,理解一流的表达式比理解特殊的形式和thunk更容易。
恕我直言,上面的意思是“一流表达式”(例如
WHILE ......
)意味着某些仅被评估部分的表达式,即惰性评估。
问:
如此维基百科链接所示,一等公民(包括 SICP 中定义的一等功能)定义:
这些操作通常包括作为参数传递、从函数返回以及分配给变量。
这与上述一流表达的特殊用法关系不大。那么什么是一等表达式,为什么可以像注释中所说的那样“代替一等函数”呢?
为了执行作为数据接收的表达式,您需要能够在运行时解释它。许多 Lisp 方言,例如 Common Lisp,都有
EVAL
函数,允许运行时执行。
但是Scheme没有这个功能。所有要执行的表达式都必须位于源代码中,而不是数据中。
SICP 确实有一章展示了如何编写元循环评估器。您可以使用它来实现您自己的
EVAL
。然而,这将受到一定的限制,因为它无法访问词法环境。因此要计算的表达式不能引用调用 EVAL
的环境的局部变量。 CL 内置的 EVAL
也有类似的限制。