注意:你的代码是不允许的#的最后一个版本的球拍不改变语言操作。进入语言>选择语言并取消选中“强制常量定义”。你会放松一些优化机智这个未经检查。
five
是类似于(lambda (n) (set! five (* 5 4 3 2 1 n)))
的延续,通过使用两个继续,您可以在一次调用后重新定义five
。之后评估five
当和(* 5 4 3 2 1 4)
为时回复(* 5 4 3 2 1 1)
的答案。
计划/球拍中的变量没有类型,但值有。这意味着变量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
考虑标线1#。在fact/k
中,默认情况下运行n 5..1,因此您可以用(define five (call/cc (lambda (five-k) (* 5 4 3 2 1 (fact/k 0 five-k)))))
替换该行。而不是fact/k
返回一个数字它使用继续呼叫,并通过它作为值是从fact/k
称为f
延续。 如果您接着在#2上评估five
,则会获得f
延续。用数值参数调用f
成为计算的最后一个答案,因为我们放弃它并返回f,所以从未发生过。 在#3中,您将以4作为参数调用five
。延续是时间旅行,所以你现在回到(define five (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``and that is set to
五since setting the variable is done *after the calculation of it's value*. On line #4 you verify that
五`确实已从延续更改为值。它的价值被改变成完全不同的类型之一。你不能拨打电话号码。
在DrRacket你可以按调试按钮,并通过它。我建议你试试看。
想想我差点拿到了。但为什么五个反弹增殖?这是否与延续的开始是从函数返回的事实有关? (从事实/ k基本情况)。可能是我错过了一些关于call/cc如何理解的概念性知识。 – chamibuddhika 2014-12-13 13:39:04
@chamibuddhika我已经更新了我的答案。这是因为调用延续将会跳转到代码中。 'five'的绑定是'k'和'f'的延续的一部分 – Sylwester 2014-12-13 14:39:57