A capture block is a first-class value enclosed in { … }.
Positional arguments are accessed via #1, #2, etc.
Call a capture with #cap(args) or #cap->invoke(args).
local(add) = { #1 + #2 }
#add(3, 4) // 7
#add->invoke(10, 5) // 15
An auto-collect capture ({^ … ^}) accumulates each produced value
into a buffer. Call the capture to retrieve the concatenated result.
local(cap) = {^
'Hello'
', '
'world'
^}
#cap() // 'Hello, world'
#cap->autoCollectBuffer // same
Captures close over the local variables in scope at the point they are created:
local(prefix) = 'Hi '
local(greet) = { #prefix + #1 }
#greet('Ada') // 'Hi Ada'
// captured variable is mutable
local(count) = 0
local(tick) = { #count = #count + 1 }
#tick
#tick
#count // 2
Iteration and control methods accept an associated capture block with =>:
// auto-collect result from loop
loop(3) => {^ loop_count + ' ' ^}
// '1 2 3 '
// forEach with associated block
array('x', 'y', 'z')->forEach => {
#1->uppercase
}
// early exit via non-local return
define first_even(items) => {
#items->forEach => {
#1 % 2 == 0 ? return #1
}
return null
}
first_even(array(1, 3, 4, 6)) // 4
->detach turns a capture into a resumable coroutine.
yield suspends execution and returns a value to the caller.
Calling the capture again resumes from the next expression after yield.
local(series) = {
yield 1
yield 2
yield 3
}->detach
#series() // 1
#series() // 2
#series() // 3
#series->restart // reset to start
Locals created before a yield survive the resume.
->restart resets the program counter and restores the creation scope.
| Method | Description |
|---|---|
#cap(args) | Call / resume the capture. |
#cap->invoke(args) | Same as calling directly. |
#cap->continue | Resume without passing a value. |
#cap->resume | Resume (alias for continue). |
#cap->detach | Detach and return the capture as a coroutine. |
#cap->restart | Reset to start of capture body. |
#cap->home | Return to the home caller. |
#cap->continuation | The underlying resumable continuation. |
#cap->autoCollectBuffer | Contents of the auto-collect buffer. |
#cap->isDetached | True if the capture is detached. |
#cap->isResumable | True if a resume is possible. |
protect => { … } establishes an error scope.
fail raises an error. handle_failure registers a handler
capture that receives the error as #1.
protect => {
handle_failure => { 'caught: ' + error_msg }
fail('something went wrong')
}
// 'caught: something went wrong'
protect => {
handle_failure(-type='auth') => {
'auth error: ' + error_msg
}
handle_failure => {
'other error: ' + error_msg
}
fail(-type='auth', -code=403, 'access denied')
}
// 'auth error: access denied'
protect => {
handle_failure => {
error_msg // message string
error_type // type tag, if set
error_code // numeric code, if set
rethrow // re-raise the same error
}
fail('boom')
}
Inside a running capture, currentCapture and currentContinuation
expose diagnostic information:
local(cap) = {
currentCapture->id
currentCapture->isDetached
currentCapture->isResumable
currentCapture->metadata // source_line, home_method, etc.
}
#cap()