The ret!()/throw!() macros
The underlying control flow constructs of these two macros are return.
However, ret!()/throw!() macros are preferred over return because:
-
Using
returnis subject to changes on feature oflog/env_log, while usingret!()/throw!()are not. -
ret!()/throw!()are cool and more clear thanreturn. -
ret!()supports Ok-wrapping.
The syntax of ret!()
-
ret!( ok_value ), or -
ret!( result_value )
In other words, you can use ret!() to return an Ok expression:
#![allow(unused)] fn main() { #[cex] fn foo() -> Result!( i32 throws String ) { ret!( 42 ); // Ok-wrapping } }
or you can use ret!() to return a Result expression:
#![allow(unused)] fn main() { #[cex] fn foo() -> Result!( i32 throws String ) { ret!( Ok( 42 )); // or ret!( Err( String::from( "oops" ))) } }
The syntax of throw!()
is throws!( err_value ).
You can use throw!() to return an Err expression:
#![allow(unused)] fn main() { #[cex] fn foo() -> Result!( i32 throws String, SomeError ) { throw!( String::from( "oops" )) // or throw!( SomeError ) } }
Thanks to the power of Exchange:
#![allow(unused)] fn main() { #[cex] fn bar() -> Result!( i32 throws String, &'static str, SomeError ) { match foo() { Ok(v) => ret!(v), Err(e) => throw!(e), // all errors in foo()'s throws are in bar()'s } } }
Thanks to the power of ? which looks like throwing checked exceptions:
#![allow(unused)] fn main() { // equivalent to bar() #[cex] fn baz() -> Result!( i32 throws String, &'static str, SomeError ) { ret!( foo()? ) // of course you can use `?` to propagate errors } }