std/core/control
std/core/src/control.trb
Control structures that are ordinary functions.
Only constructs that bind names (const, fn, type, ...) or jump (if, match, for, while) are built in.
fn do
fn do<Value>(body: () => Value): Value
Evaluates a block immediately: const x = do { ... }
fn unless
fn unless(condition: Bool, body: () => Void)
Runs the block unless the condition holds: if !condition { ... }, for a guard that reads better negated.
fn retry
fn retry<Value, Failure>(times: Int, action: () => Result<Value, Failure>): Result<Value, Failure>
const response = retry 3 { http.get(url) }
trait Close
shared trait Close
The destructor of an object: what releases the resource behind it - a descriptor, a socket, a lock - once nothing holds the object any more.
Only a shared type implements it, because a value is copied on assignment and two copies would close one resource
twice. No program calls close(): the last release of the object runs it, and a program that wants that moment
early lets the scope end or binds the object with using name = value, whose name cannot leave its block. Inside
close(), self may not be stored, returned or captured by a closure that outlives the call.
Examples
shared type Connection with Close {
var isOpen: Bool = true
fn send(message: String) {
print message
}
var fn close() {
isOpen = false
}
}
fn greet() {
using connection = Connection()
connection.send "hello"
}
Open
No back end runs close() at the last release yet (docs/design/DESTRUCTORS.md, slice R1), so a program that needs
a resource released today has no way to ask for it.
fn close
var fn close()
Releases the resource. Runs exactly once, when the last reference to the object goes away; it returns nothing,
cannot fail and never waits, and a type whose graceful end can do either offers end() beside it.