Macro fluent_comparisons::any_of [−][src]
macro_rules! any_of { ( {$($lh_sides:expr),+}.satisfy($($func:tt)+) ) => { ... }; ( {$($lh_sides:expr),+}.map($($func:tt)+) $operator:tt $rhs:expr) => { ... }; ( {$($lh_sides:expr),+} $operator:tt $rhs:expr) => { ... }; }
Compare all values in a set to a common right hand side and decide whether the comparison returns true
for any of the values in the set.
Lazy Evaluation
If we write any_of!({a,b}<c)
, this is equivalent to the hand coded a<c && b<c
. That means that the comparisons are
evaluated lazily from left to right. Once
the truth value of the expression can be determined, the evaluation stops. That means that e.g. for the expression any_of!({1,some_func()}<5)
,
the function some_func()
is not invoked.
Usage
Basic Usage
For the basic use case we compare a set of values against a common right hand side. Invoke the macro using
any_of!({/*list of expressions*/} operator rhs)
, where operator can be any of the binary comparison operators, i.e.
==
, !=
, <=
, <
, >
, and >=
. The list of expressions on the left hand side is comma separated without a trailing comma. The right hand side
is an expression as well.
The list of expressions can have a variadic number of elements but must have at least one. It must always be enclosed in curly braces. The expressions on the left hand side need not be of the same type, but the comparison with the right hand side must be valid. In particular, the expressions need not be numeric.
use rand::prelude::*; // given: let square = |val|val*val; let v = vec![1, 2,3]; let mut rng = rand::thread_rng(); // the following assertions hold assert!(any_of!({1,2,3}>2)); assert!(any_of!({4+4+1,square(7*2),120_i32.pow(2)}>8)); assert!(any_of!( {rng.gen::<usize>(),v.len(),2,1+1,"hello world".len()} == v.len()));
Usage with Transformations
We can also apply a transformation to the list on the left hand side before comparing to the right hand side.
For that, simply append .map(...)
to the list and give an argument that transforms the values. The argument
to map can be any kind of invokable of a single argument, like a function or closure. Here the type requirements
are a bit stricter and all values on the left hand side must be of the same type.
// given let square = |x|x*x; // the following assertions hold assert!(any_of!({4,square(2),2_i32.pow(2)}.map(|x|x+5)>8)); assert!(any_of!({4+1,3,5}.map(square)==9));
Usage with Predicates
This is a special case where the transformation maps to a boolean predicate. Instead of writing
any_of!({...}.map(/*predicate f:x -> bool*/)==true)
, we can use the syntax any_of!({...}.satisfy(/*predicate f:x -> bool*/))
,
which saves us the comparison with true
on the right hand side. Don’t use a predicate which
compares values with one of the comparison operators, because then you are better served with the
syntax above. Rather use it for more complex predicates:
fn is_prime_number(x:i32) -> bool { /*some interesting math*/ }; //this assertion holds assert!(any_of!({12,14,5}.satisfy(is_prime_number)));