Macro tuplez::unary_pred
source · macro_rules! unary_pred { ($($t:tt)*) => { ... }; }
Expand description
Provides a simple way to build a unary predicate that implements UnaryPredicate
.
§Syntax
Generic = [Lifetime1, Lifetime2, ...] [Type1 [: Bound1], Type2 [: Bound2], ...]
Rule = [ < Generic > ] | Variable : InputType | { Body } [,] [;]
unary_pred!( [Rule1 Rule2 ... ] )
§Explanation
A unary predicate rule is much like a closure, except that it must annotate the element type, and what you actually get is the immutable reference to the element rather than itself.
|x: i32| { *x > 10 } // The actual type of `x` is `&i32` not `i32`
Note that it’s just like but not really a closure, so you can’t capture context variables.
You’d better not annotate types for the return value of rules,
because they must return a bool
value. Of course you can do that,
but there would be no advantage other than potential compilation errors.
You can also introduce generic types like this:
<T: Fn(i32) -> bool> |f: T| { f(1) }
Construct unary predicate rules for all element types in the tuple,
and then combine them in the unary_pred!
macro to test the tuple:
use tuplez::{tuple, TupleLike, unary_pred};
let tup = tuple!(1, "2", |x: i32| x >= 0);
let result = tup.all(
unary_pred! {
|x: i32| { *x >= 0 }
|x: &str| { !x.is_empty() }
<T: Fn(i32) -> bool> |f: T| { f(1) }
}
);
assert_eq!(result, true);
It is allowed to add commas or semicolons as separators between rules. Sometimes this may look better.
§As a Mapper
In fact, this macro does not directly implement UnaryPredicate<T>
for the
underlying type. Instead, it implements Mapper<&T, Output=bool>
.
Therefore, you can definitely use it as a Mapper
like this:
use tuplez::{tuple, TupleLike, unary_pred};
let tup = tuple!(Some(1), "", |x: i32| x == 0);
let result = tup.as_ref().foreach(
unary_pred! {
|x: Option<i32>| { x.is_some() }
|x: &str| { !x.is_empty() }
<T: Fn(i32) -> bool> |f: T| { f(1) }
}
);
assert_eq!(result, tuple!(true, false, false));