2

我仍然不明白动态解释器与词汇解释器有何不同。

我正在研究方案,我发现很难知道像这样的简单代码如何动态地和词法地工作。

(define mystery
  (let ((x 2018))
    (lambda (y)
      (let ((result (cons x y)))
         (set! x (+ x 1))
         result))))

任何指导?

4

3 回答 3

1

词法绑定具有有限的可见性和无限的寿命。所有函数都“记住”它们创建的环境——这种函数称为词法闭包

在您的示例中,这部分:

(let ((x 2018))
    (lambda (y) (let ((result (cons x y)))
                  (set! x (+ x 1)) result))))

返回函数,它记住 x = 2018 的环境。该函数绑定到符号mystery,当您调用它时,它会更改该环境中 x 的值。

> (mystery 1)
'(2018 . 1)
> (mystery 1)
'(2019 . 1)

在具有动态绑定(无限可见性、有限生命周期)的 Scheme 中,函数不记得创建它们的环境。因此,函数mystery不会记住 x = 2018 的环境,并且(mystery 1)在评估期间调用以错误结束(cons x y),因为符号x没有价值。

于 2021-08-10T11:20:26.513 回答
0
(define mystery
  (let ((x 2018))
    (lambda (y)
      (let ((result (cons x y)))
         (set! x (+ x 1))
         result))))

这不是一个很好的例子来理解动态绑定和静态绑定之间的区别。这只是一个角落案例。

这个想法是,在静态绑定中,自由变量与静态范围(编写时可见的词法代码)相关联,而在动态绑定中,它们与动态代码(存储在执行堆栈上的内容)相关联。

您的代码计算result结果为以下 lambda 表达式:

(lambda (y)
  (let ((result (cons x y)))
    (set! x (+ x 1))
    result))

在这个结果中,唯一的自由变量是X

将结果应用于 的值时 X 的值是Y多少?

在静态作用域中,它将是 2018,在动态绑定中,X 的值将存储在堆栈中——例如,

(define X 100)
(define F (result 200)))

将应用result绑定X=100(X 将保留在堆栈中)。当然,X 的值并没有物理地保存在堆栈中,只是指向它所在的环境框架的指针,或者如果在环境上执行了重新生根,则可能保存在值单元中,等等。

要了解您的误解,您可以参加 lambda 演算课程。而且,当然,我在这里所说的假设您使用通用解释,许多其他解释可以与与您的输入示例相同的语法相关联,等等。

于 2021-08-24T14:54:35.540 回答
0

让我们用您的代码制作一个程序:

;; a global binding
(define x 100)

;; your function
(define mystery
  (let ((x 2018))
    (lambda (y)
      (let ((result (cons x y)))
         (set! x (+ x 1))
         result))))

;; just to add newlines in prints
(define displayln
  (lambda (v) 
    (display v)
    (newline)))

;; a indirect call
(define local-test 
  (lambda (x)
    (displayln x)
    (displayln (mystery 'local))
    (displayln (mystery 'local))
    (displayln x)))

(define global-test
  (lambda ()
    (displayln x)
    (displayln (mystery 'global))
    (displayln (mystery 'global))
    (displayln x)))

;; program
(local-test 1)
(local-test 11)
(global-test 1)
(global-test 11)

正常 Scheme 的结果仅依赖于闭包,而不依赖于调用堆栈绑定变量:

1
(2018 local)
(2019 local)
1
11
(2020 local)
(2021 local)
11
1
(2022 global)
(2023 global)
1
11
(2024 global)
(2025 global)
11

动态“方案”的结果具有神秘的死代码。它什么也不做,因为绑定没有与函数对象一起保存。因此只有 activelet和 calls 中的变量匹配:

1
(1 local)
(2 local)
3
11
(11 local)
(12 local)
13
100
(100 global)
(101 global)
102
102
(102 global)
(103 global)
104
于 2021-08-13T11:45:49.950 回答