On Dec 1, 2012, at 7:28 PM, Galler wrote:

> I've been thinking about a reified continuation:
> 
> The documentation (See Guide s10.3) says "A continuation is a value that
> encapsulates a piece of an expression context"


Someone should submit a doc bug report to the Guile people. The 'expression' 
should be replaced (or supplemented) with 'evaluation'. 



> I'm coming to the belief that the continuation is actually  "an ordered
> collection of computation-branches, with facilities provided to manipulate
> one member of the collection"
> 
> For example:
> 
> (+ (+ 1 2) (let/cc k 3) (+ 2 3))
> 
> which yields 11
> 
> If we were to capture  k in a module level variable *k*, we can substitute 4
> for the result of the third ordinal branch (counting from the left)
> 
> (*k* 4)
> 
> and get a value of 12, etc. Indeed, we can substitute any value for the
> third ordinal branch.
> 
> So my question is:
> 
> What's so special about the third branch?
> 
> Is there any reason I couldn't change the fourth branch, or second, or even
> first?
> 
> Put another way, why doesn't the reified continuation k expose the
> individual branches?


Some of your thinking is correct. Some is incorrect. 

Let's calculate with *some* fixed order (left to right, for another order say 
right to left or middle out you'd get similar results): 

(define *k* #f) (+ (+ 1 2) (let/cc k (save-k-in-*k*-and-return k 3)) (+ 2 3))
|--> 
(define *k* #f) (+ 3 (let/cc k (save-k-in-*k*-and-return k 3)) (+ 2 3))
|--> 
;; Now you have *k* bound to a procedure reflection of the evaluation context 
of (let/cc k ...). 
(define *k* (\ (x) (abort (+ 3 x (+ 2 3)))) (+ 3 3 (+ 2 3))
|--> 
(define *k* (\ (x) (abort (+ 3 x (+ 2 3)))) (+ 3 3 5)
|--> 
(define *k* (\ (x) (abort (+ 3 x (+ 2 3)))) 11 

Okay, let's play with *k* now. Well, as it is there are about four operators on 
procedures that you can use in our world: 
 -- application: (*k* ?)
 -- (procedure? *k*)
 -- (arity-includes *k*)
 -- (object-name *k*)
And that's it. So when we made the language design choice to reify evaluation 
contexts around (let/cc ...) as procedures, we determined what we could do. 

Now imagine that we lied. We don't really reify evaluation contexts as 
[continuation] procedures but as [continuation] objects with additional 
operations for inspecting and possibly mutating them. One could imagine that 
continuations are organized as a [abstract] sequence of [abstract] frames: 

  (+ 2 3)
  3
  +  

The language could then provide operations such as set-frame : Continuation 
Natural Value -> Continuation (or an imperative version thereof) and with this 
operation you could do this: 

 (set-frame *k* 2 -) 

and that would produce 

  (+ 2 3)
  3
  -

Before you do so, you might run (if (eq? (object-name (get-frame *k* 2)) '+) 
... ...) to make sure you are really replacing the addition operator. 

What you canNOT do even in this world is visit the past and perform a different 
computation than (+ 1 2). The best you can do is change frame 2 so that it is 
99 instead of 3 but that's not changing the computation. [Imagine the 
computation performed I/O or a set!.]

This idea shows up in Felleisen, Wand, Friedman, Duba, LISP 1988, "Abstract 
Continuations." 

MIT Scheme treats continuations as lists of frames, and SICM exploits this 
ability to perform mathematical operations on functions. In this context you 
can, for example, set-car! (cddr *k*) and then reflect *k* (and hope for the 
best). I admire people who program in this way but I am not sure I want to live 
in this world myself. 

-- Matthias

  






____________________
  Racket Users list:
  http://lists.racket-lang.org/users

Reply via email to