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));