1

我正在阅读 r6rs(Revised6 Report on the Algorithmic Language Scheme),在“介绍”部分有一个总结:

“Scheme 是 Lisp 的第一个主要方言,用于区分过程与 lambda 表达式和符号,为所有变量使用单一的词法环境,并以与操作数位置相同的方式评估过程调用的运算符位置。”

我的问题是:

“将过程与 lambda 表达式和符号区分开来”有什么好处?

什么是单一的词汇环境?我的理解是,由于词法范围,Scheme 中的所有内容都是“词法”,没有运行时范围,源代码中的位置/位置更多地意味着环境。

如何理解“以与操作数位置相同的方式评估过程调用的运算符位置”?我的理解是运算符位置的符号被评估为操作数位置。例如:

(define test
    (lambda (x)
        ((if (> x 0) + -) 1 2)))

"(if (> x 0) + -)" 在操作符位置,它的求值与其他操作数位置的求值相同。

4

2 回答 2

2

Scheme 是第一个拥有词法环境和闭包的 Lisp。它对 Common Lisp 的设计产生了相当大的影响。词法环境的替代方案是动态绑定。例子:

;; setup (on both)
(define v 10)

(define (adder v)
  (lambda (x) (+ x v))))

;; lexical scheme results
(define add5 (adder 5))
(add5 3) ; ==> 8
(let ((v 6))
  (add5 3)) ; ==> 8

;; dynamic scheme results
(define add5 (adder 5))
(add5 3) ; ==> 13 (since y is the global variable 10)
(let ((v 6))
  (add5 3)) ; ==> 9 (since v is bound to 6 during the call to add5)

Scheme 没有动态变量,所以最后一部分不会发生。Common Lisp 实际上具有全局定义变量的动态范围,因此如果您可以在 CL 中实际测试它:

(defparameter *v* 10)
(defparameter *x* 0)

(defun adder (*v*)
  (lambda (*x*) (+ *x* *v*))))

;; lexical scheme results
(defparameter *add5* (adder 5))
(funcall *add5* 3)    ; ==> 13
(let ((*v* 6))
  (funcall *add5* 3)) ; ==> 9

有些 lisp 方言只有动态绑定。picoLisp 和 elisp 的早期版本就是例子。

请注意,Common Lisp 使用funcall的是因为我已将函数绑定到变量。那是因为它们有两个命名空间。一种用于评估操作员位置的表格,另一种用于其余位置。因此,在 CL 中,您可以list命名函数和参数list,它们是不同的值。下面是在 Scheme 中不起作用但在 CL 中可以正常工作的代码:

(let ((list '(1 2 3)))
  (list list list))

; ==> ((1 2 3) (1 2 3)) in CL
; ==> Application: (1 2 3) is not a procedure error in Scheme
于 2017-03-24T12:11:24.903 回答
1

什么是单一的词汇环境?

好吧,Scheme 有一个词法环境,但是旧的 lisps 可以有多个词法环境。例如,如果您为函数(名称)和参数(名称)维护单独的环境,那么您可以编写:

> (define (foo foo) (+ foo 3))
> (foo 4)
7

“以与操作数位置相同的方式评估过程调用的运算符位置”?

当您有一个环境用于函数而另一个环境用于参数时,过程调用使用函数参数来查找运算符,并使用另一个环境来查找参数。

另请参阅此答案(由 Kent Pittman 撰写)并点击链接到有关 lisp-1 与 lisp-2 的论文。

“Lisp-1 vs Lisp-2”与静态类型的语言相关吗?

于 2017-03-22T17:06:29.450 回答