Arc Forumnew | comments | leaders | submitlogin
Help w/ continuations
2 points by antiismist 6011 days ago | 9 comments
I find CPS to be pretty straightforward to grok, e.g.:

  (def set-cool (i c (o cont))
     (= i!cool c)
     (save-post i)  
     (aif cont (it)))
and then when I call set-cool:

(w/link (set-cool i "not-cool" indexnew) (prn "not-cool"))

Can the same control flow be done with continuations? (I haven't been able to wrap my head around continuations yet...)



2 points by conanite 6011 days ago | link

This Sam Ruby article helped me a lot with continuations:

http://www.intertwingly.net/blog/2005/04/13/Continuations-fo...

A continuation behaves just like a one-arg function except it never returns to its caller. It returns to the point where it was created. This might upset the flow of the app server. Also, the app server relies on redirecting stdout to the network socket, and jumping to a saved continuation appears to restore stdout to whatever it was for that continuation.

I wonder if arc is intended to support full re-callable continuations - official arc only references 'ccc once, in the 'point macro, which is only used for 'catch. And the intent of 'catch (i think) is only to provide an escape mechanism, not a re-callable continuation.

I'm guessing that official arc uses ccc in a limited way because (I read somewhere that) arc was originally built on Common Lisp, not Scheme, and CL doesn't support full continuations. But I might be completely wrong. And maybe ccc is one of the reasons arc switched to scheme. Somebody on this forum knows the truth ...

-----

2 points by tokipin 6010 days ago | link

i'm currently writing a blog post featuring Arc's ccc, and all signs point to it being a 100% implementation. this shouldn't be too surprising since (i believe) the compiler transforms the Arc code to CPS

i don't know what the OP is asking exactly, but the answer is likely yes. i implemented coroutines, so these more straightforward things should be no problem

i talk about it a bit on the blog post, but the problem with continuations is the freaken name. it sounds like some sophisticated thing, when in fact all it is is marking the next instruction. for example:

  (ccc func)
obviously you're using ccc here because you want to go back to it later. perhaps you want to go back to it from within 'func'. in other words, so that 'func' effectively has the ability to arbitrarily return:

  (ccc [do (stuff...)
        (if blah (_ bleh)) ; early return
        (do more stuff)])
but what if control returned right back precisely to ccc? then the whole form would be executed again. see how that would be a problem? so ccc doesn't mark the "current" spot. it marks the next spot so you don't get stuck in an infinite loop

and because it's the next spot, and because you can call _ as a function, they refer to it with the holistic name "continuation," instead of "the spot after the ccc"

they could have just as easily made the primitive be mark-the-current-spot, a la:

  (ccc [= spot _])
but while making mark-the-current-spot with ccc is easy, the converse isn't, nor would mark-the-current-spot necessarily be the most common use form (the impetus for call/cc might have been to give scheme the ability to return)

-----

1 point by absz 6010 days ago | link

Actually, arc just compiles everything down to Scheme; Scheme, of course, has full continuation support, and thus so does Arc.

That's a nice explanation of continuations, but one comment: I think (if I remember what I read correctly) that writing ccc in terms of mark-the-current-spot (or perhaps get/cc, or gcc :P) is actually impossible, but I could be wrong. The other advantage of ccc is that every flow control construct can be simulated using it (including, but not limited to, C's return).

-----

2 points by tokipin 6010 days ago | link

> I think (if I remember what I read correctly) that writing ccc in terms of mark-the-current-spot (or perhaps get/cc, or gcc :P) is actually impossible, but I could be wrong.

that's the short-term conclusion i came to when i was fidding with it. i didn't exactly prove it was the case though so i was being safe

-----

1 point by almkglor 6010 days ago | link

You might also want to mention continuation guards and dynamic-wind (which is partially exposed as 'protect in Arc).

-----

2 points by stefano 6011 days ago | link

This is one of the few cases where it would be better to have some specifications other than the source code itself. A compliant implementation should support full continuations, because one could write programs that rely on ccc and those programs would work on ArcN.tar.

-----

2 points by almkglor 6010 days ago | link

> This is one of the many cases

fixed that for you ^_^ \/

For example, consider the minor problem of macros such as 'w/infile:

  (restartable
    (pr "Press enter to begin processing the file")
    (readline)
    (w/infile p "thefile.txt"
      (whilet l (readline p)
        (when (is l "foo\n")
              (prn "A \"foo\" was found in the file!")
              (prn "Please correct these errors first")
              (restart)))
      (prn "finished processing!")))
The point is that 'restart is really a continuation bound to the beginning of the 'restartable form. Obviously 'w/infile and related forms must trap continuations; the mzscheme implementation uses 'dynamic-wind, exposed as the 'protect function.

This is one of the many cases where having an explicit specification would have been nice, because this would have required some code digging. What, exactly, is 'protect intended to do?

-----

2 points by stefano 6010 days ago | link

The problem is increased by the fact that the official arc implementation drains entire constructs (such as 'dynamic-wind) from the underlying scheme. How should we consider them when writing an alternative implementation? Are they intended to have the identical behavior of the corresponding scheme constructs? An official test suite would be really helpful and would solve most of the problems.

-----

1 point by antiismist 6011 days ago | link

Thanks for the pointer. Looks like ccc is not going to help me here

-----