Run parallel work with tasks
This recipe starts two computations before awaiting either result, then joins successful and failing Result tasks through one explicit propagation boundary.
Project tree
text
tasks/
└── main.kmSource
ts
import go errors from "errors";
import go fmt from "fmt";
function square(value: int): int {
return value * value;
}
function load(ready: boolean): Result<int> {
if (!ready) { return fail(errors.New("not ready")); }
return ok(7);
}
function joinedResult(ready: boolean): Result<int> {
const task: Task<Result<int>> = go load(ready);
const value = await task?;
return ok(value * 2);
}
function main(): void {
const first = go square(4);
const second = go square(5);
const firstValue = await first;
const secondValue = await second;
const [checked, checkedErr] = joinedResult(true);
const [failed, failedErr] = joinedResult(false);
fmt.Println(
firstValue, secondValue,
checked, checkedErr === nil,
failed, failedErr !== nil,
);
}Run
sh
keika check main.km
keika run main.kmExpected output:
text
16 25 14 true 0 trueLifecycle contract
- Each
go square(...)expression starts a worker and returnsTask<int>. - The call target and argument evaluate synchronously once before that worker starts.
- Both tasks exist before the first
await, allowing their work to overlap. - Every binding is consumed exactly once.
- A worker panic is transported and re-panicked by its
await. Task<Result<int>>has two completion layers:awaitjoins the worker, then postfix?propagates its ordinary operation error.- The successful result is doubled to
14; the failed result returns theintzero value and a non-nil error.
The compiler rejects an unconsumed, copied, reassigned, captured, stored, escaped, or multiply consumed task. One such invalid program is part of the documentation test suite.
The await task? spelling is valid inside a compatible Result function. Awaiting without ? is rejected because Result is an effect, not a value that can be stored after the join.
Pass context.Context explicitly when work requires cancellation; automatic context inheritance is not implemented.