Scheme 中的范围 (Lisp)

标签 scope scheme lisp lexical

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

   (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

最佳答案

您的两个代码块具有相似的语法。一个词法变量 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)

原因是动态处理语言没有闭包,因此当 make-incer 返回过程时 n 不存在,因此 n 是全局绑定(bind)或更近的调用时间绑定(bind),如下所示:

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

关于Scheme 中的范围 (Lisp),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39841078/

相关文章:

angularjs - 为什么设置$location.path时需要scope.$apply

javascript - 去抖关闭

scheme - 在哪里可以找到关于Scheme中 "use"指令的文档?

lisp - 这段 Lisp 代码做了什么?

Perl:如何使需要脚本中的变量在所需脚本中可用

c++ - 限制 C++ 变量的作用域

python - 如何在 Sage Math 中使用 Scheme 而不是 Python

scheme - Chez 方案 : Macroexpand implementation

stream - 写入后读取 *standard-input* Common Lisp

database - Common Lisp 中的函数持久化