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)*))?)?
fn $fname:ident $({$($ty_params:tt)*})?
($($args:tt)*)
-> $ret_ty:ty =>! $err_ty:ty
where {
$($wc:tt)*
}
) => { ... };
(
$(#[$meta:meta])*
$(pub $(($($vis:tt)*))?)?
fn $fname:ident {$($ty_params:tt)*}
($($args:tt)*)
-> $ret_ty:ty =>! $err_ty:ty
) => { ... };
(
$(#[$meta:meta])*
$(pub $(($($vis:tt)*))?)?
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(())
!
#[macro_use] extern crate candy;
use ::std::{
*,
io::Write,
};
fallible! {
fn main ()
-> ()
=>! String
:
if try_print_all(&[0b101010, 0x45]).is_err() {
throw!("Could not write to stdout");
};
}
fallible! {
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!(
fn try_into (
self: Self,
) -> T
=>! Self::Err);
}
fallible! {
fn bar <X, Displayable> (
x: X,
) -> String
=>! X::Err
where {
Displayable : fmt::Display,
X : TryInto<Displayable>,
} {
let displayable = x.try_into()?;
format!("{}", displayable)
}}