【问题标题】:Funky call/cc usage. How does it work?时髦的通话/抄送用法。它是如何工作的?
【发布时间】:2014-12-12 23:17:42
【问题描述】:

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

(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。

$5

120

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

我知道最初有五个点指向在(零?n)基本情况下捕获的延续。但我不确定如何解释上述行为。

另一个参数不同的运行

$(5 4)

五美元

480

【问题讨论】:

    标签: lambda scheme racket callcc


    【解决方案1】:

    注意:在不更改语言选项的情况下,#!racket 的最新版本中不允许使用您的代码。进入语言>选择语言并取消选中“强制常量定义”。如果不选中此选项,您将失去一些优化。

    five 是类似于(lambda (n) (set! five (* 5 4 3 2 1 n))) 的延续,通过使用两个延续,您可以在一次调用后重新定义five。之后评估five 可以得出(* 5 4 3 2 1 1) 的答案,当参数是1(* 5 4 3 2 1 4),当它是4

    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
    

    考虑标记线#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 tofivesince setting the variable is done *after the calculation of it's value*. On line #4 you verify thatfive` 确实已经从延续变为值。它的值更改为完全不同的类型之一。你不能拨打一个号码。

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

    【讨论】:

    • 想我几乎明白了。但是为什么五是反弹到乘法呢?这与延续的开始是函数的返回有关吗? (来自事实/k 基本情况)。可能是我缺少一些关于 call/cc 如何工作的概念性知识来理解这一点。
    • @chamibuddhika 我已经更新了我的答案。这是因为调用延续就像跳转到代码中一样。 five 的绑定是 kf 延续的一部分
    猜你喜欢
    • 2010-10-11
    • 2010-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多