"区分程序与lambda表达式和符号的好处"

时间:2017-03-22 05:17:21

标签: lambda scheme evaluation lexical r6rs

我正在阅读r6rs(修订版6关于算法语言方案的报告),在"简介"部分有一个摘要:

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

我的问题是:

"区分程序与lambda表达式和符号的好处"?

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

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

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

"(if(> x 0)+ - )"在操作员位置,其评估与其他操作数位置的评估相同。

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

  

单一的词汇环境是什么?

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

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

“以与以下相同的方式评估过程调用的操作员位置   操作数位置“?

如果有一个函数环境而另一个环境用于参数,则过程调用使用函数参数来查找运算符,使用其他环境来查找参数。

另见这个答案(肯特皮特曼以外的其他人),并点击关于lisp-1 vs lisp-2的论文的链接。

Is "Lisp-1 vs Lisp-2" relevant in a language with static types?