Continuations
Continuations in Atomo are very simple, and probably more powerful than they should be.
But this is not a language for the faint of heart.
Just keep in mind that when you use continuations, you'd better be careful how you use them - and be sure that you're not using a cannon to hammer a nail. With great power comes great responsibility.
NOTE: A few of these examples need to use blocks to get around limitations of Anatomy's interactive examples, so they may be a bit long.
Continuation → Object
A Continuation is a value that represents the context of an expression that was evaluated; what was being done with it, and whatever was going to happen next.
o call/cc → any | o responds-to?: @call:
Sends the current Continuation to o.
When the continuation is yielded to, the appropriate before/after thunks (provided by before:after:, et al.) are unwound.
o call/cc: (... args) → any | o responds-to?: @call:
Like call/cc, but sends some additional arguments along to the block.
The continuation is the first argument, followed by args.
c yield: v → any | c is-a?: Continuation
Immediately go back to c's context and yield v in its place.
action before: pre-thunk after: post-thunk → any | [action, pre-thunk, post-think] all?: @(is-a?: Block)
Calls the three blocks in order, returning action's result.
In addition; post-thunk is always called, even if an exception is raised.
pre-thunk is called whenever action is re-entered (e.g. by jumping back into it by yielding to a continuation).
post-thunk is called whenever control leaves the block (e.g. by yielding to another continuation) or when action completes.
init wrap: cleanup do: action → any | init is-a?: Block | cleanup responds-to?: @call: | action responds-to?: @call:
Calls action with the init's result, ensuring that cleanup is performed when control leaves action and that init is re-calleded and passed to action when control enters action.
current-continuation → Continuation
Returns the current continuation.
Be careful, though: by current, it really means current. You usually want to use call/cc.
For example, if you assign this to a value, the continuation will be that assignment:
> { a = current-continuation; a print; (a yield: 42) when: (a is-a?: Continuation); @done } call <continuation> 42 @done
We had to check if a was a Continuation there, because after the yield: it becomes 42, and you'd end up with 42 yield: 42. That is, execution continues from just after the assignment, with a as its new value, which it happily attempts to yield: to all over again.
c yield → any | c is-a?: Continuation
c yield: @ok.
c call → any | c is-a?: Continuation
c yield: @ok.