Hacker News new | past | comments | ask | show | jobs | submit login

The bizarre thing about continuations is that you can call a function once and return from it an arbitrary number of times. It seems like this would break invariants in any function that takes a callback argument but doesn't expect the callback to save a continuation?

If the continuation could be resumed at most once, this would be more like suspending a thread/fiber and resuming it later.




If your function takes a callback and you save a continuation inside of it, then one of two things happen:

- if you call the callback before you save the continuation, then the callback isn't ever called again (unless you call the whole function again, of course).

- if you call the callback after saving the continuation, then the callback is called whenever you resume the continuation.

So basically, resuming the continuation is equivalent to either never calling the callback, or calling the callback like normal. It sounds weird, but everything works out.


I meant the case where the function doesn't use continuations at all. It calls the callback. The callback saves a continuation. Then the callback could return more than once to a function that doesn't know anything about continuations.


Ah, yeah. So in that case the stack frame is set up exactly as it was whenever the continuation is saved. If your function's output is based entirely on its input, you'll get the same result each time. If it uses some state (like incrementing a member variable) then that action happens each time the continuation is invoked.

EDIT: Sorry, I think you were saying you know what they do but that it seems like that'd break all kinds of invariants. It's true that you have to consider scenarios a bit more carefully, but I find it's not that much of a burden compared to the benefits.


I think common lisp's restart system and/or delimited continuations handle most of the "reasonable" uses of continuations without some of the less intuitive aspects of full continuations.


> I think common lisp's restart system and/or delimited continuations handle most of the "reasonable" uses of continuations without some of the less intuitive aspects of full continuations.

As you may know, Oleg makes the same argument, that call/cc has a lot of problems, and, in practice, isn't really used anyway: http://okmij.org/ftp/continuations/against-callcc.html#illus... . (EDIT: I see that sillysaurus (https://news.ycombinator.com/item?id=14680711) linked this same discussion a while ago.)


Delimited continuations are the full ones.

The so-called full continuations lack the flexibility to put the delimiting prompt anywhere but the top-level entry point to the program or thread.

Delimited continuations are complete in the sense that they let the programmer control where the top is.

Put the delimiting prompt around the top-level startup function and you have a "full" continuation.


From the description in th article, it seems like the content of the stack frame is usually not saved, which would break a lot of code that modifies a variable on the stack. E.g. if you are incrementing a counter in a loop and save a continuation into the middle of the loop, then on each invocation of that same continuation, the loop counter might have different values.

The obvious fix would be to never modify the content of a stack frame, instead recreating it with a different value for each iteration, but that doesn't strike me as very efficient.


All local variables are saved by a continuation. EDIT: Nope.


This can be easily demonstrated false in Scheme. Two continuations which capture the same environment can mutate it and see each other's mutations.

A continuation captures variable bindings similarly to a closure. (It just captures more than just variable bindings and more than just the lexically apparent ones.)


Whoops. You're right, thank you.


Functions that don't know anything about continuations cannot support the capturing of continuations across them.

A function that has arguments on the stack and really returns and all that will not be happy if it invokes a callback and that callback is actually a continuation of yours that doesn't return. You have stuff on the stack that hasn't been cleaned away.




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: