我正在查看以下来自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"之后的任何代码。这是对的吗?
看起来这个代码不会起作用!实际发生了。或者是集!这段代码必须工作吗?
正在进行的视觉表现确实会有所帮助。
答案 0 :(得分: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
...
为什么呢?因为r1
首先将r2作为cont
接收,所以它向我们宣布它在r1中。然后它使用(call/cc cont)
又名(call/cc r2)
的结果来自行处理。
好的,这是什么回报?好(call/cc r2)
将开始执行r2并宣布它在r2中,然后使用(call/cc cont2)
的结果递归自身。那么什么是cont2
呢?在cont2
之前,r1
是该表达式的延续。因此,当我们在这里调用它时,我们将延续传递回我们当前所在的位置。然后我们忘记了我们在r2中做了什么,然后跳回执行r1。
现在在r1
重复。我们宣布一些东西,然后跳回到我们之前在r2中的位置和之前的表达式,(call/cc cont2)
返回我们在r1
的位置继续,然后我们继续我们的快乐无限循环。 / p>
在您的代码中,概念完全相同。实际上,当您停下来思考它时,superfluous-computation
几乎与上述功能完全相同。那么set!
s有什么用呢?在这段代码中,他们所做的就是将do-other-work
的值更改为最新的延续。而已。在我的例子中,我使用了递归。在此示例中,他们使用set!
。