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 instead

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 Result type). The error case (a failing case of a ? operator) must be handled (and recovered to a success type value) by a following => catch block.

Traits

IntoOk

This trait, which is implemented for all sized types, provides the method into_ok, which moves the value on which it is called into an Result::Ok. This is particularly useful when having to wrap a value into an Ok at the end of a call chain.

IntoSome

This trait, which is implemented for all sized types, provides the method into_some, which moves the value on which it is called into an Optional::Some. This is particularly useful when having to wrap a value into a Some at the end of a call chain.