Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用trampoline和Y combinator的代码是否应该在具有动态范围的lisp中工作?_Lisp_Lexical Scope_Dynamic Scope - Fatal编程技术网

使用trampoline和Y combinator的代码是否应该在具有动态范围的lisp中工作?

使用trampoline和Y combinator的代码是否应该在具有动态范围的lisp中工作?,lisp,lexical-scope,dynamic-scope,Lisp,Lexical Scope,Dynamic Scope,我有javascript中的lisp,它类似于scheme。它可以用于词法范围和动态范围。我不确定动态作用域是如何工作的,看起来还可以,但当作用域是动态的时,此代码不工作: (define Y (lambda (h) ((lambda (x) (x x)) (lambda (g) (h (lambda args (apply (g g) args))))))) (define (trampoline f) (lam

我有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 with demo就在这里,但是用于词法范围的代码还没有发布,所以它不会工作。它位于devel branch中,我可以使用它或使用堆栈片段创建codepen演示。

我不知道trampoline如何处理动态范围

简化评估:

(define Y ...)
现在Y与某个值绑定

(define (trampoline f)
    (lambda args
       (let ((result (apply f args)))
           ...)))
现在蹦床绑定到λfλargs,让结果应用到λf args

现在!一定是在蹦床上。。。n1

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

根据定义!上面我们将n绑定到1000并评估蹦床。。。n1

我们需要叫蹦床。根据上面蹦床的定义,我们把f和。。。并返回lambda args,让结果应用于参数

我们从蹦床上回来,解开f的束缚

我们现在需要计算lambda参数,让结果应用于f参数。。。n 1将蹦床的返回值应用于n和1

n当前绑定为1000,因此此表达式变为lambda args让结果应用于f args。。。1000 1. 为了执行调用,我们将args绑定到1000 1

现在我们需要计算apply f args,将结果绑定到result,作为let的一部分。apply位于标准库中。args刚刚绑定到1000 1以上。但对f没有约束力

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

使用Perl版本的代码进行实时演示,其中所有绑定都是手动动态的:

它会像预期的那样爆炸:不能使用未定义的值作为行local$result=$f->@args的子例程引用;因为$f是未绑定的

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

我不知道trampoline如何处理动态范围

简化评估:

(define Y ...)
现在Y与某个值绑定

(define (trampoline f)
    (lambda args
       (let ((result (apply f args)))
           ...)))
现在蹦床绑定到λfλargs,让结果应用到λf args

现在!一定是在蹦床上。。。n1

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

根据定义!上面我们将n绑定到1000并评估蹦床。。。n1

我们需要叫蹦床。根据上面蹦床的定义,我们把f和。。。并返回lambda args,让结果应用于参数

我们从蹦床上回来,解开f的束缚

我们现在需要计算lambda参数,让结果应用于f参数。。。n 1将蹦床的返回值应用于n和1

n当前绑定为1000,因此此表达式变为lambda args让结果应用于f args。。。1000 1. 为了执行调用,我们将args绑定到1000 1

现在我们需要计算apply f args,将结果绑定到result,作为let的一部分。apply位于标准库中。args刚刚绑定到1000 1以上。但对f没有约束力

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

使用Perl版本的代码进行实时演示,其中所有绑定都是手动动态的:

它会像预期的那样爆炸:不能使用未定义的值作为行local$result=$f->@args的子例程引用;因为$f是未绑定的


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

否。蹦床和Y组合器使用闭包

动态范围没有闭包,因此引用自由变量的过程/函数表示程序调用堆栈中具有该名称的任何变量

在词法范围中,它是创建lambda时捕获的变量。因此,守则:

(define test 10)

(define (make-adder test)
  (lambda (v) (+ test v)))

(define add20 (make-adder 20))

(add20 5) 
; ==> 25 in lexical scope
; ==> 15 in dynamic scope 
原因很简单。make加法器返回的函数将值20存储为test,而在动态范围中,test是绑定最接近的值,因此它是局部变量10。此外,致电时:

(let ((test 30))
  (add20 5))
; ==> 25 in lexical scope
; ==> 35 in dynamic scope
现在,CommonLisp有动态范围和词法范围。动态作用域变量是用defvar、defparameter或声明的special在顶层定义的变量。这很容易出错,因此我们使用*earmuff*对这些变量进行了特殊命名

Sche me具有可变对象的参数,并且有用于更新和恢复它的语法,以便将其用作动态变量

编辑


我已经测试了你的词法和动态lisp,两者似乎都能正常工作

不。蹦床和Y组合器使用闭包

动态范围没有闭包,因此引用自由变量的过程/函数表示程序调用堆栈中具有该名称的任何变量

在词法范围中,它是创建lambda时捕获的变量。因此,守则:

(define test 10)

(define (make-adder test)
  (lambda (v) (+ test v)))

(define add20 (make-adder 20))

(add20 5) 
; ==> 25 in lexical scope
; ==> 15 in dynamic scope 
原因很简单。make加法器返回的函数将值20存储为test,而在动态范围中,test是绑定最接近的值,因此它是局部变量10。此外,致电时:

(let ((test 30))
  (add20 5))
; ==> 25 in lexical scope
; ==> 35 in dynamic scope
现在,CommonLisp有动态范围和词法范围。动态作用域变量是用defvar、defparameter或声明的special在顶层定义的变量。这很容易出错,因此我们使用*earmuff*对这些变量进行了特殊命名

Scheme具有可变对象的参数,并且有用于更新和恢复它的语法,以便将其用作动态变量

编辑


我已经测试了你的词法和动态lisp,两者似乎都能正常工作

哦,看来我的动态范围毕竟是错的,因为它应该抛出错误,f是未定义的,它什么也不做。它是抛出的,但只是在控制台中,因为它是在承诺中。哦,所以看来我的动态范围毕竟是错误的,因为它应该抛出错误,f是未定义的,它什么也不做。它抛出了,但只是在控制台中,因为它是在承诺中。