In rust, it's possible to pass >
or <=
etc inside macro arguments so long as the arguments are ident
s.
Is it possible to create a macro that lets you chain comparison operators?
let x = 3;
let y = 1;
let z = -3;
assert_eq!(cond!(z <= x > y), true);
Yes you can. You need to use tt
for the operator type:
macro_rules! cond {
(@rec ($head:expr) $last:ident $op:tt $next:ident $($tail:tt)*) => {
cond!(@rec (($head) && ($last $op $next)) $next $($tail)*)
};
(@rec ($head:expr) $last:ident) => { $head };
($first:ident $op:tt $next:ident $($tail:tt)*) => {
cond!(@rec ($first $op $next) $next $($tail)*)
}
}
fn main() {
let x = 3;
let y = 1;
let z = -3;
println!("(z <= x > y) = {}", cond!(z <= x > y));
}
Playground
You can also read The little book of Rust Macros for more advanced macros patterns.
I think the following does what you expect as long as you are careful with the arguments to cond
.
It uses tt
(for argument operator0
) to match <
, <=
, >=
, etc. to avoid repeating lots of cases, but tt
, of course, matches other tokens, too.
macro_rules! cond{
($x:ident $operator0:tt $x0:ident) => {
($x $operator0 $x0)
};
($x:ident $operator0:tt $x0:ident $($operator1:tt $x1:ident)*) => {
($x $operator0 $x0) && cond!($x0 $($operator1 $x1)*)
};
}
fn main() {
let x = 3;
let y = 1;
let z = -3;
assert_eq!(cond!(z <= x > y), true);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With