[][src]Macro candy::fallible

macro_rules! fallible {
    (
        $(#[$meta:meta])*
        $vis:vis
        fn $fname:ident $({$($ty_params:tt)*})?
            ($($args:tt)*)
        -> $ret_ty:ty =>! $err_ty:ty
        where {
            $($wc:tt)*
        }
            $fbody:tt
    ) => { ... };
    (
        $(#[$meta:meta])*
        $vis:vis
        fn $fname:ident {$($ty_params:tt)*}
            ($($args:tt)*)
        -> $ret_ty:ty =>! $err_ty:ty
        :
            $($fbody:tt)*
    ) => { ... };
    (
        $(#[$meta:meta])*
        $vis:vis
        fn $fname:ident
            ($($args:tt)*)
        -> $ret_ty:ty =>! $err_ty:ty
        :
            $($fbody:tt)*
    ) => { ... };
    (
        $(#[$meta:meta])*
        $(pub $(($($vis:tt)*))?)? // $vis:vis does not work here :(
        fn $fname:ident $({$($ty_params:tt)*})?
            ($($args:tt)*)
        -> $ret_ty:ty =>! $err_ty:ty
        where {
            $($wc:tt)*
        }
    ) => { ... };
    (
        $(#[$meta:meta])*
        $(pub $(($($vis:tt)*))?)? // $vis:vis does not work here :(
        fn $fname:ident {$($ty_params:tt)*}
            ($($args:tt)*)
        -> $ret_ty:ty =>! $err_ty:ty
    ) => { ... };
    (
        $(#[$meta:meta])*
        $(pub $(($($vis:tt)*))?)? // $vis:vis does not work here :(
        fn $fname:ident
            ($($args:tt)*)
        -> $ret_ty:ty =>! $err_ty:ty
    ) => { ... };
    (
        $(#[$meta:meta])*
        $(pub $(($($vis:tt)*))?)?
        fn $fname:ident
        < $($other:tt)*
    ) => { ... };
    (@unsugaring_ty_params
        $(#[$meta:meta])*
        $(pub $(($($vis:tt)*))?)?
        fn $fname:ident
        [ < ]
        $type_parameters:tt
        > $($other:tt)*
    ) => { ... };
    (@unsugaring_ty_params
        $(#[$meta:meta])*
        $(pub $(($($vis:tt)*))?)?
        fn $fname:ident
        [ $($depth:tt)* ]
        {$($type_parameters:tt)*}
        < $($other:tt)*
    ) => { ... };
    (@unsugaring_ty_params
        $(#[$meta:meta])*
        $(pub $(($($vis:tt)*))?)?
        fn $fname:ident
        [ < $($depth:tt)* ]
        {$($type_parameters:tt)*}
        > $($other:tt)*
    ) => { ... };
    (@unsugaring_ty_params
        $(#[$meta:meta])*
        $(pub $(($($vis:tt)*))?)?
        fn $fname:ident
        $depth:tt
        $type_parameters:tt
        >> $($other:tt)*
    ) => { ... };
    (@unsugaring_ty_params
        $(#[$meta:meta])*
        $(pub $(($($vis:tt)*))?)?
        fn $fname:ident
        $depth:tt
        { $($type_parameters:tt)* }
        $single_tt:tt $($other:tt)*
    ) => { ... };
}

Sugar for the pervasive -> Result<T, E> fallible return type pattern.

It transforms it into -> T =>! E, and disposes of the need to wrap the implicit return value of the function in a Ok(...). In other words, no more Ok(())!

Example

//! Run with `cargo run --example fallible`

#[macro_use] extern crate candy;

use ::std::{
    *,
    io::Write,
};

fallible! {
/// Basic usage
fn main ()
    ->  ()
    =>! String
:
    if try_print_all(&[0b101010, 0x45]).is_err() {
        throw!("Could not write to stdout");
    };
}

fallible! {
/// Using it with type parameters
pub fn try_print_all <Iterable: IntoIterator<Item = impl fmt::Debug>> (
    iterable: Iterable,
)   ->  ()
    =>! io::Error
:
    let to_stdout = &mut io::stdout();
    write!(to_stdout, "[")?;
    let mut iterator = iterable.into_iter();
    if let Some(first) = iterator.next() {
        write!(to_stdout, "{:?}", first)?;
        while let Some(next) = iterator.next() {
            write!(to_stdout, ", {:?}", next)?;
        };
    };
    write!(to_stdout, "]\n")?;
}

trait TryInto<T> {
    type Err;

    fallible!(
    /// Using it with a function header
    fn try_into (
        self: Self,
    )   ->  T
        =>! Self::Err);
}

fallible! {
/// Using it with `where` clauses (/!\ Need braces /!\)
fn bar <X, Displayable> (
    x: X,
)   ->  String
    =>! X::Err
where {
    Displayable : fmt::Display,
    X : TryInto<Displayable>,
} {
    let displayable = x.try_into()?;
    format!("{}", displayable)
}}