Option, Result, and ?
Question-mark evaluates a canonical Result once, unwraps Ok, or returns the identical Err type through cleanup edges.
DByte 12.0 · Language
Contract§
fn add_two(input: Result[u32, u32]) -> Result[u32, u32]:
let value = input?
return Result[u32, u32].Ok(value + (2 as u32))
pub fn kernel_main() -> int:
let result = add_two(Result[u32, u32].Ok(40 as u32))
match result:
case Result.Ok(value):
if value != (42 as u32):
return 1
case Result.Err(error):
return error as int
return 0
Source: source-examples/v12.0.0/result_match.dby
fn add_two(input: Result[u32, u32]) -> Result[u32, u32]:
let value = input?
return Result[u32, u32].Ok(value + (2 as u32))
pub fn kernel_main() -> int:
let result = add_two(Result[u32, u32].Ok(40 as u32))
match result:
case Result.Ok(value):
if value != (42 as u32):
return 1
case Result.Err(error):
return error as int
return 0
Mechanics§
Question-mark evaluates its Result operand once, branches on the canonical tag, yields the Ok payload or constructs/returns the identical Err type. Active defer cleanup edges are inserted on the propagation branch.
Validation and failure§
Only canonical Result is accepted. The enclosing function or closure must return the same error TypeId; there is no implicit conversion, exception or unwinding.
Evidence and boundary§
Adversarial tests count single evaluation and cleanup order; native proof executes both success and error propagation.
Executable example§
fn add_two(input: Result[u32, u32]) -> Result[u32, u32]:
let value = input?
return Result[u32, u32].Ok(value + (2 as u32))
pub fn kernel_main() -> int:
let result = add_two(Result[u32, u32].Ok(40 as u32))
match result:
case Result.Ok(value):
if value != (42 as u32):
return 1
case Result.Err(error):
return error as int
return 0