gpt4 book ai didi

lisp - 带有蹦床和 Y 组合器的代码是否应该在具有动态范围的 lisp 中工作?

转载 作者:太空宇宙 更新时间:2023-11-03 18:51:32 25 4
gpt4 key购买 nike

我在 javascript 中有 lisp,类似于 scheme。它可以与词法和动态范围一起使用。我不确定动态作用域是如何工作的,它看起来没问题,但是当作用域是动态的时,这段代码不起作用:

(define Y
(lambda (h)
((lambda (x) (x x))
(lambda (g)
(h (lambda args (apply (g g) args)))))))

(define (trampoline f)
(lambda args
(let ((result (apply f args)))
(while (eq? (type result) "function")
(set result (result)))
result)))

(define (! n)
((trampoline (Y (lambda (f)
(lambda (n acc)
(if (== n 0)
acc
(lambda ()
(f (- n 1) (* n acc)))))))) n 1))

(print (! 1000))

当范围是词法时,它工作正常。当范围是动态的时,这段代码应该工作吗?现在它什么都不做,我不知道为什么,但我想确保这段代码在我开始调试之前能正常工作,并因此使我的动态范围中断。

我的 lisp 演示在这里 https://jcubic.github.io/lips/但是使它在词法范围内工作的代码尚未发布,因此它不会工作。 (它在 devel 分支中,我可以用它或使用 Stack Snippet 创建 codepen 演示)。

最佳答案

我不明白 trampoline 如何与动态范围一起工作。

简化评估:

(define Y ...)

现在 Y 被绑定(bind)(到某个值)。

(define (trampoline f)
(lambda args
(let ((result (apply f args)))
...)))

现在 trampoline 绑定(bind)到 (lambda (f) (lambda args (let ((result (apply f args))) ...)))

(define (! n)
((trampoline ...) n 1))

现在 ! 绑定(bind)到 (lambda (n) ((trampoline ...) n 1))

(print (! 1000))

我们首先评估内部调用,因此我们需要解析 ! 并将其应用于 1000

根据上面 ! 的定义,我们将 n 绑定(bind)到 1000 并评估 ((trampoline ...) n 1)

我们需要调用trampoline。根据上面trampoline的定义,我们将f绑定(bind)到...,并返回(lambda args (let ((result (apply f args))) ...)).

我们从 trampoline 返回并取消 f 的绑定(bind)。

我们现在需要评估 ((lambda args (let ((result (apply f args))) ...)) n 1)(应用 trampoline< 的返回值n1)。

n 当前绑定(bind)到 1000,因此此表达式变为 ((lambda args (let ((result (apply f args))) ... )) 1000 1)。为了执行调用,我们将 args 绑定(bind)到 (1000 1)

现在我们需要评估 (apply f args)(将结果绑定(bind)到 result 作为 let 的一部分)。 apply 在标准库中。 args 刚刚绑定(bind)到上面的 (1000 1)。但是 f 没有绑定(bind)。

在这一点上我们应该抛出一个错误:到目前为止我们看到的唯一的 f 绑定(bind)是在调用 trampoline 期间(其中 f 是一个参数)。但是那个调用已经返回并且绑定(bind)被删除,所以 f 是未绑定(bind)的。


现场演示(使用代码的 Perl 版本,其中所有绑定(bind)都是手动动态化的):https://ideone.com/DWjwBj

如预期的那样爆炸:不能使用未定义的值作为子例程引用 local $result = $f->(@args);因为 $f 是未绑定(bind)的。

如果您将所有绑定(bind)更改为词法绑定(bind)(将所有出现的 local 替换为 my),$fac->(5) 返回 120 符合预期。

关于lisp - 带有蹦床和 Y 组合器的代码是否应该在具有动态范围的 lisp 中工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52339296/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com