Crate fn_block[−][src]
Library for wrapping a block or expression into a closure and call it
Introduction
The functionality of this crate was defined, because every now and then it is unpractical,
that the ?
operator in rust has a "unwrap or return" semantic. In many other languges
(such as Swift, C#, Kotlin, etc.) the ?.
operator allows "safe navigation",
and this would be practical for the Option
and Result
type in Rust every now and then.
The navigation code could be extracted to another function,
but oftentimes this would fragment code that actually belongs together.
Another workaround is to wrap a ?.
call chain into a closure and
call it directly. For example, consider the following piece of code:
let o = Some("Foobar"); let s = o.and_then(|st| st.get(0..3)).map(|st| st.to_lowercase()); assert_eq!("foo", s.unwrap());
The second line would be more readable using the ?.
navigation. But this would lead
to a return from the entire function if an empty option is being accessed. So the call
chain can be wrapped into a cosure which is then immediately called. The following code
shows, how the previous example can be written in this style:
let o = Some("Foobar"); let s = (|| Some(o?.get(0..3)?.to_lowercase()) )(); assert_eq!("foo", s.unwrap());
While this code is very terse, it is not necessarily the easiest to read.
The fn_block
crate provides functionality to make the code above
a little easier to read:
let o = Some("Foobar"); let s = fn_expr!{ o?.get(0..3)?.to_lowercase().into_some() }; assert_eq!("foo", s.unwrap());
It was considered to provide a version of the macros that automatically
calls into()
on the result of the expression/block. This would allow an automatic
conversion of a value to the actual return type, provided a fitting implementation
of the Into
trait was in scope. But this was considered too implicit. The ?
operator
already performs implicit conversion of error types.
Unstable features
To enable unstable features, the crate feature unproven
must be enabled
explicitly. Here is an example dependency declaration that can be added to
a users Cargo.toml
file to enable the unstable features:
[dependencies]
fn_block = { version = "0.2.0", features = ["unproven"] }
Note that this crate's unstable features do work on stable Rust.
The unstable macro fn_try!
does call an expression in a lambda and does wrap
the sucess value into a Result::Ok
. It then enforces to recover from the error type
in a following => catch
block. The reasons behind this descision is documented in
the fn_try!
documentation.
Overly simple example usage:
use std::str::from_utf8; use std::error::Error; struct ConvertErr(); impl <T: Error> From<T> for ConvertErr { fn from(_: T) -> ConvertErr {ConvertErr()} } let bytes : &[u8] = &[0x0020,0x0034,0x0032]; let res_int = fn_try!{ from_utf8(bytes)?.trim().parse::<u32>()? => catch { ConvertErr() => 0u32 } }; assert_eq!(res_int, 42);
A more verbose and realistic version of the example above is available in
the fn_try!
documentation.
Macros
fn_block |
[ Deprecated ] NOTE: This macro has been deprecated! Use |
fn_expr |
This macro wraps a given rust code block into a closure and directly calls the closure. Optionally the return type of the closure can be specified first and separeted with a colon from the body expression. |
fn_try |
This macro wraps a given rust code expression into a closure and
directly calls the closure. The result type of the expression is expected
to be an "unwrapped" sucess value (not a |
Traits
IntoOk |
This trait, which is implemented for all sized types,
provides the method |
IntoSome |
This trait, which is implemented for all sized types,
provides the method |