Closures
Closures
A closure is a callable value. The type is written closure(A, B) => R, and the
literal uses the closure keyword:
let handler: closure(string) => string = closure(params: string) => string {
return `{"ok":true}`
}Closures are used wherever a callback is needed, most visibly when registering handlers:
application.on("ide.fs.tree", closure(params: string) => string {
let parsed: json::JsonValue = json::parse(params)
if parsed.kind() != "object" {
return `{"ok":false}`
}
return `{"ok":true}`
})Captures
A closure captures the variables it uses. When it needs a value from the enclosing scope that outlives the current frame, the capture list makes that explicit:
application.on("ide.agent.start", closure[application](params: string) => string {
application.emit("ide.agent:event", `{"t":"log","text":"started"}`)
return `{"ok":true}`
})The names in brackets after closure are captured by the closure and stay
reachable for as long as it does. Without the capture, a variable that goes out
of scope before the closure runs is not available to it.
Storing closures
A closure is an ordinary value, so it can be held in a field or a collection:
class Bridge {
[private] handlers: Map<string, closure(string) => string>
[mutates] fn on(method: string, handler: closure(string) => string) {
this.handlers.set(method, handler)
}
}