Lambda Funky call/cc用法。它是如何工作的?

Lambda Funky call/cc用法。它是如何工作的?,lambda,scheme,racket,callcc,Lambda,Scheme,Racket,Callcc,考虑以下定义。我在用球拍 (define fact/k (lambda (n k) (cond ((zero? n) (call/cc (lambda (f) (k f)))) (else (* n (fact/k (sub1 n) k)))))) (define five (call/cc (lambda (k) (fact/k 5 k)))) 现在,如果它调用如下 (五) 它什么也不发出。这样做之后,如果直接调用5,则得到120 五美元 120 但是如

考虑以下定义。我在用球拍

(define fact/k
  (lambda (n k)
    (cond
      ((zero? n) (call/cc (lambda (f) (k f))))
      (else (* n (fact/k (sub1 n) k))))))

(define five (call/cc (lambda (k) (fact/k 5 k))))
现在,如果它调用如下

(五)

它什么也不发出。这样做之后,如果直接调用5,则得到120

五美元

120

但是如果我重试(5 1),它会失败,说120不是一个过程

据我所知,最初在(0?n)基本情况下捕获的连续性有五个点。但我不确定如何解释上述行为

使用不同参数运行另一次

元(五元四角)

五美元


480

NB:在最新版本的#中不允许使用您的代码!不改变语言操作的球拍。进入语言>选择语言并取消选中“强制常量定义”。您将失去一些未经检查的优化

five
是一个类似于
(lambda(n)(set!five(*5 4 3 2 1 n))
的延续,通过使用两个延续,您可以在一次调用后重新定义
five
。当参数为
1
时,对
5
进行评估,然后查看
(*54321)
的答案;当参数为
4
时,对
(*543214)
进行评估

Scheme/Racket中的变量没有类型,但值有。这意味着一个变量
five
可以首先是一个过程/延续,然后是一个数字。这就是你所看到的情况

编辑重述一下我的名字:

(define fact/k
  (lambda (n k)
    (cond
      ((zero? n) (call/cc (lambda (f) (k f))))
      (else (* n (fact/k (sub1 n) k))))))

(define five (call/cc (lambda (k) (fact/k 5 k)))) ; #1
five ; ==> #<continuation>, f to be precise         #2
(five 4)                                            #3
five ; ==> 480                                      #4
(定义事实/k
(λ(北k)
(续)
((零分)(呼叫/抄送(lambda(f)(kf)))
(其他(*n(事实/k(子1 n)k()())))
(定义五个(call/cc(lambda(k)(fact/k5k)))#1.
五个;==>#,f准确地说是#2
(五个4)#3
五个;==>480                                      #4
考虑到标记线#1。在
fact/k
中,默认情况下为n5..1运行,因此您可以用
替换该行(定义五(call/cc(lambda(五-k)(*54321(fact/k0five-k)'))
)。它使用continuation调用返回一个数字,而不是
fact/k
,它作为值传递的是
fact/k
调用的
f
中的continuation。 如果然后在#2上计算
five
,则得到
f
继续。使用数值参数调用
f
将成为计算的最后一个答案,因为我们中止了计算并返回了f。 在#3中调用
five
,4作为参数。延续是一种时间旅行,所以现在您可以回到
(定义五(call/cc(lambda(five-k)(*5 4 3 2 1(fact/k 0 five-k‘);)
,您只知道
(fact/k 0 five-k)
计算为
4
。接下来发生的事情是,
(*5 4 3 2 1 4)
变为
480``并且设置为
5
,因为变量的设置是在计算其值*之后*完成的。
在第4行,您确认
five`确实已从一个continue更改为一个value。它的值被更改为一个完全不同的类型。你不能打电话


DrRacket中,您可以点击debug按钮并单步执行。我建议你试试看

我想我快拿到了。但为什么五是反弹到乘法?这是否与继续的开始是函数的返回这一事实有关?(来自事实/k基本情况)。可能是我缺少了一些关于call/cc如何工作的概念性知识来理解这一点。@chamibuddhika我已经更新了我的答案。这是因为调用continuation就像跳入代码。
five
的绑定是
k
f