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-called
ed 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
.