5

我正在查看来自http://community.schemewiki.org/?call-with-current-continuation的协程的以下示例:

 (define (hefty-computation do-other-stuff) 
    (let loop ((n 5)) 
      (display "Hefty computation: ") 
      (display n) 
      (newline) 
      (set! do-other-stuff (call/cc do-other-stuff)) ; point A
      (display "Hefty computation (b)")  
      (newline) 
      (set! do-other-stuff (call/cc do-other-stuff)) 
      (display "Hefty computation (c)") 
      (newline) 
      (set! do-other-stuff (call/cc do-other-stuff)) 
      (if (> n 0) 
          (loop (- n 1))))) 

多余的工作:

 ;; notionally displays a clock 
 (define (superfluous-computation do-other-stuff) 
    (let loop () 
      (for-each (lambda (graphic) 
                  (display graphic) 
                  (newline) 
                  (set! do-other-stuff (call/cc do-other-stuff))) 
                '("Straight up." "Quarter after." "Half past."  "Quarter til.")) ; point B
      (loop))) 


(hefty-computation superfluous-computation) 

对于 call/cc 的第一次使用,上下文应该是什么?当我说上下文时,我的意思是由于 callcc 的跳转,我们应该“返回”到哪里?

据我了解,第一次调用 call/cc 时,do-other-stuff 本质上变成了一个过程,执行多余计算的代码,然后在集合之后立即跳转到该点!(A点)。第二次,它将“跳转到 B 点”行为包裹在“跳转到 A 点并执行上下文,或 A 点之后的任何代码”周围。它是否正确?

如果设置,此代码似乎不起作用!实际发生了。或者是套装!这段代码有必要工作吗?

对正在发生的事情进行可视化表示确实会有所帮助。

4

1 回答 1

4

的上下文call/cc是从哪里call/cc调用的。您几乎可以想到一个call/cc类似的方法goto,它将代码直接跳回到您之前的位置并(call/cc whatever)用返回值替换。

call/cc基本上是说,“让我们去做这个功能,然后放弃它,然后跳回到这里,忘记它在做什么”

好的,当我第一次尝试理解call/cc时,我发现这段代码非常混乱,所以让我们看一个简化的协程示例:

(define r1
  (lambda (cont)
    (display "I'm in r1!")
    (newline)
    (r1 (call/cc cont))))

(define r2
  (lambda (cont2)
    (display "I'm in r2!")
    (newline)
    (r2 (call/cc cont2))))

好的,这与您的代码的概念完全相同。但这要简单得多。

在这种情况下,如果我们称之为(r1 r2)打印

I'm in r1
I'm in r2
I'm in r1
I'm in r2    
I'm in r1
I'm in r2    
I'm in r1
I'm in r2
...

为什么?因为r1first 接受 r2,cont所以它向我们宣布它在 r1 中。(call/cc cont)然后它以aka的结果在自身上递归(call/cc r2)

好的,那么这有什么回报?well(call/cc r2) 将开始执行 r2 并宣布它在 r2 中,然后以(call/cc cont2). 好的,那cont2又是什么?cont2是 in 之前该表达式的延续r1。因此,当我们在这里调用它时,我们会将一个延续传回我们当前所在的位置。然后我们忘记了我们在 r2 中所做的任何事情并跳回执行 r1。

r1这在现在重复。我们宣布内容,然后跳回到我们之前在 r2 中的位置和我们之前的表达式,(call/cc cont2)返回一个延续到我们所在的位置r1,然后我们继续我们的快乐无限循环。

返回您的代码

在您的代码中,概念完全相同。其实superfluous-computation和上面的功能几乎是一模一样的,你停下来想一想。那么set!s怎么了?在这段代码中,他们所做的只是将 的值更改为do-other-work最新的延续。就是这样。在我的示例中,我使用了递归。在这个例子中,他们使用set!.

于 2012-11-12T05:39:27.923 回答