Continuation概念学习历程
(define retry #f) (define factorial (lambda (x) (if (= x 0) (call/cc (lambda (k) (set! retry k) 1)) (* x (factorial (- x 1))))))
- (factorial 4) => 24
- 此时retry,也就是continuation可以描述为:(Take the value)Multiply the value by 1, then multiply this result by 2, then multiply this result by 3, then multiply this result by 4.
- 这一点应当这么理解:define时,程序没有执行,不存在什么continuation,因为continuation代表的就是computation,只有运行时的程序才是computation。因此当(factorial 4)时,其计算流就是(* 4 (* 3 (* 2 (* 1 (factorial 0))))),即(* 4 (* 3 (* 2 (* 1 (call/cc (lambda (k) (set! retry k) 1)))))),此时才可以明确retry的含义。注意:此时k并没有进行application,因此(call/cc)的值是返回的1,也就是(factorial 4)=(* 4 (* 3 (* 2 (* 1 1))))=24,k仅以(call/cc ...)整体作为the value来进行描述。
- 此时retry,也就是continuation可以描述为:(Take the value)Multiply the value by 1, then multiply this result by 2, then multiply this result by 3, then multiply this result by 4.
- (factorial 5) => 120
- 有了上面的分析,这里就很好理解了,那么retry,即k有(k x)=(* 5 (* 4 (* 3 (* 2 (* 1 x)))))
- (retry 1) => 120
- (retry 2) => 240
2024-04-05
- What does with-continuation mean? 对Continuations最好的实例解释。其截图使用了Snap工具。该文进行了完整截图:#697
- 这里对GOTO的讲解也极其重要,它引出了对Continuation的计算机程序方面的实质定义:Continuation就是当前代码语句在Stack上的Stack Frame,而不仅仅是传统GOTO接受的一条指令Address。Goto到Procedure内部的指令Address,由于没有走正常函数调用流程,就没有正常的push栈帧过程,极有可能造成严重问题,而离开该Procedure时,又会执行pop栈帧的动作,更是会引发严重问题。
- Continuations 主要是该文末尾的引用很好
- Continuations by example: Exceptions, time-traveling search, generators, threads, and coroutines. 这个个人网站有很多非常精彩的文章
- Continuations这个描述的非常清楚。
- During the evaluation of a Scheme expression, the implementation must keep track of two things: (1) what to evaluate and (2) what to do with the value.
- We call "what to do with the value" the continuation of a computation.
- "the value"就是(call/cc ...)的值
- Scheme allows the continuation of any expression to be captured with the procedure call/cc. call/cc must be passed a procedure p of one argument. call/cc constructs a concrete representation of the current continuation and passes it to p. The continuation itself is represented by a procedure k. Each time k is applied to a value, it returns the value to the continuation of the call/cc application. This value becomes, in essence, the value of the application of call/cc.
- 注意下面这两个实例分析,非常重要:
(let ([x (call/cc (lambda (k) k))]) (x (lambda (ignore) "hi"))) => "hi"
The continuation captured by this invocation of call/cc may be described as "Take the value, bind it to x, and apply the value of x to the value of (lambda (ignore) "hi")."
这一段对continuation的描述可以当做一个模板,套在对任何continuation的描述上。
即捕获的continuation是:Take the value(这个value就是(call/cc)的值),bind it to x【可选动作,若有,则x即为该continuation】,and apply the continuation(是个有一个参数的Procedure) to the value of other S-expressions.
对应到上面这个例子,捕获的continuation就是:Take the value(此value就是(call/cc)的值,此处就是continuation本身,即procedure k),bind it to x(即x也被赋值为该continuation),最后apply the value of x to the value of (lambda (ignore) "hi")。
那么在执行到(x (lambda (ignore) "hi"))语句时,就是以(lambda (ignore) "hi")为参数调用procedure k,其执行流就是:Take the value(此处value就是(lambda (ignore) "hi")函数),bind it to x(就是将x赋值为(lambda (ignore) "hi")),and apply the value of x to the value of (lambda (ignore) "hi"),即((lambda (ignore) "hi") (lambda (ignore) "hi")),结果自然就是“hi”
(((call/cc (lambda (k) k)) (lambda (x) x)) "HEY!")
套用上面的分析,就很简单了。这个continuation是:Take the value, apply the value to (lambda (x) x) to produce a new value, then apply the new value to "HEY!"
这个continuation就是procedure k,因此这行代码就是((k (lambda (x) x)) "HEY!"),根据k的解释,执行过程就是:- Take the value,即参数(lambda (x) x)
- apply the value to (lambda (x) x) to produce a new value,即((lambda (x) x) (lambda (x) x)),其值为(lambda (x) x)
- apply the new value to "HEY!",即((lambda (x) x) "HEY!"),得最终结果"HEY!"
2022-09-07
(call/cc (lambda (current-continuation) ...))
这是call/cc的参数:一个lambda函数,且该lambda接受一个参数,且该参数是current-continuation
(+ 1 (call/cc (lambda (cc) (cc 2))))
上面这个例子中,(+ 1 █)里去掉黑洞后就是那个call/cc的continuation,很明显,这个continuation其实就是一个函数,它接受一个int型作为参数,也就是这里的黑洞。即这里的continuation=(lambda (█) (+ 1 █))
这个例子的结果:3
要记住:当call/cc里出现cc的调用时,第一个cc函数调用产生的结果就是cc跨越的作用域的代码块的值。
这个例子的结果:3
要记住:当call/cc里出现cc的调用时,第一个cc函数调用产生的结果就是cc跨越的作用域的代码块的值。
(* 100 (+ 1 (call/cc (lambda (k) (+ 2 9) (k 2) (k 1)))))
上面这个表达式的值就是第一个cc的调用,即(k 2)就是整个代码块的值,因为k=(lambda (█) (* 100 (+ 1 █))),所以值为300
(* 100 (+ 1 (call/cc (lambda (k) (+ 2 9)))))
上面这个表达式里没有cc的调用,那么在call/cc里没有出现cc的调用时,call/cc调用就是一个普通的函数调用,返回(+ 2 9)=11,然后完成剩余的计算(* 100 (+ 1 11))=1200
2022-08-31
- CSE 341: Scheme: Continuations and exceptions
- An expression's continuation is "the computation that will receive the result of that expression". ;;表达式的continuation.
- 如(+ 4 (+ 1 2))中,表达式(+ 1 2)的continuation就是+4这个computation
- An expression's continuation is "the computation that will receive the result of that expression". ;;表达式的continuation.
- Beautiful Racket Explainer: Continuations
- A continuation is a special kind of function that’s like a bookmark to the location of an expression.
2022-05-23
- p0534r3.pdf:call/cc (call-with-current-continuation): A low-level API for stackful context switching
- 意图将call/cc在C++里标准化
- A continuation is an abstract concept that represents the context state at a given point during the execution of a program.
- As a basic, low-level primitive it can be used to implement control structures like coroutines, generators, lightweight threads, cooperative multitasking (fibers), backtracking, non-deterministic choice.
- The remainder of the computation derived from the current point in a program’s execution is called the current continuation.
- call/cc captures the current continuation and passes it to the function invoked by call/cc.