This k@v
is a notation used by the author, which represents the reification of execution context (or continuation) v@(...)
. You can think of a execution context as a call stack in imperative language, but that is not a good way to think. The good way is to think is as a textual representation.
For example,
(+ 1 (+ 1 (+ 1 ?)))
This text above represents a continuation around the ?
, where ?
is a expression. We say that (+ 1 (+ 1 (+ 1 ?)))
is the continuation of ?
.
In the author's blog, his v@(...)
denotes some continuation, e.g. (+ 1 (+ 1 (+ 1 ?)))
, and k@v
represents the reification of v@(...)
. Notice that the continuation (+ 1 (+ 1 (+ 1 ?)))
is very like a procedure and ?
represents a place to plug in a value. The reification of v@(...)
is exactly a such procedure (with effect).
I have relabeled the call/cc
to make it clearer:
a@(call/cc1 call/cc2) ; line1
=> a@(call/cc2 k@a) ; line2
=> (k@a k@a) ; line3
=> k@a ; line4
The line1-> line2 just means 2 step:
call/cc1
capture the continuation a@
and reify it to k@a
- apply
call/cc2
to k@a
.
P.s. You may also wonder what happened after that.
Alas, I think the author made a small bug here (although it does affect the final result of that blog), it should be written:
a@(call/cc1 call/cc2) ; line1
=> a@(call/cc2 k@a) ; line2
=> a@(k@a k@a) ; line3
=> a@k@a ; line4
The line2-> line3 means:
call/cc2
capture the continuation a@
- reify it to
k@a
, then apply k@a
to k@a
.
The line3-> line4 means:
- throw away
a@
- plug the right
k@a
to the context of the left k@a
, thus result a@k@a
If we following the author's deriving, i.e. a@(call/cc1 call/cc2) => k@a
, then (call/cc call/cc)
will throw away the current context, but obviously it's not the case:
(let ()
(printf "111\n")
(let ((k (call/cc call/cc))) ; <--- continue execute after (call/cc call/cc), not jump to toplevel
(printf "222 k=~a\n" k)
(set! *k* k))
(printf "333\n"))
;; 111
;; 222 k=#<procedure>
;; 333
Correct me if i'm wrong.