计划范围(Lisp)

时间:2016-10-03 22:00:30

标签: scope scheme lisp lexical

我知道该方案是一种词法范围/静态范围的语言,但我不明白为什么这两个代码块会返回不同的结果。

   (define a 100)
   (let ((z 20))
      (lambda (a b) (+ a b)) a z)
  

20

 (define a 100)
 (let ((z 20)) 
      (lambda (a b) (+ a b)) z a)
  

100

1 个答案:

答案 0 :(得分:7)

您的代码块都具有相似的语法。一个词法变量z,包含两行死代码和一个尾部位置的表达式,它们成为let的结果。例如

(let ((z 20))
  (lambda (a b) (+ a b)) ; evaluates to a procedure and thrown away
  a                      ; evaluated to 100 and thrown away 
  z)                     ; evaluated to 20. in tail so the result of let

第二个非常相似:

 (let ((z 20)) 
   (lambda (a b) (+ a b)) ; evaluates to a procedure and thrown away
   z                      ; evaluated to 20 and thrown away
   a)                     ; evaluated to 100. In tail so the result of let

请注意,从不应用(调用)评估过程的lambda。打电话给他们,例如。使用其他表达式作为参数,您会得到完全不同的结果:

(let ((z 20))
  ; calls the anonymous lambda with agruments a and z
  ((lambda (a b) (+ a b)) a z)) ; ==> 120

括号在这种语言中很重要。太少了,你会得到单独的表达式,其中最后一个是结果。太多了,你不小心应用了非程序的值。

另请注意,在动态范围的lisp中,您将获得相同的结果。但是在这:

(define n 100)
(define (make-incer n)
  (lambda (x) 
    (+ n x)))

(define inc10 (make-incer 10))
(inc10 5) 
; ==> 15 (lexically scoped) 
; ==> 105 (dynamicly scoped)

原因是dymamicly应对语言不具有闭包,因此当n返回过程时make-incer不存在,因此n是全局的绑定或更接近的通话时间绑定,如:

(let ((n 5))
  (inc10 20)) 
; ==> 30 (lexically scoped)
; ==> 25 (dynamically scoped)