How to write a macro in Rust to match any element in a set? - macros

In C, I'm used to having:
if (ELEM(value, a, b, c)) { ... }
which is a macro with a variable number of arguments to avoid typing out
if (value == a || value == b || value == c) { ... }
A C example can be seen in Varargs `ELEM` macro for use with C.
Is this possible in Rust? I assume it would use match. If so, how would variadic arguments be used to achieve this?

macro_rules! cmp {
// Hack for Rust v1.11 and prior.
(#as_expr $e:expr) => { $e };
($lhs:expr, $cmp:tt any $($rhss:expr),*) => {
// We do this to bind `$lhs` to a name so we don't evaluate it multiple
// times. Use a leading underscore to avoid an unused variable warning
// in the degenerate case of no `rhs`s.
match $lhs { _lhs => {
false || $(
cmp!(#as_expr _lhs $cmp $rhss)
) || *
// ^- this is used as a *separator* between terms
}}
};
// Same, but for "all".
($lhs:expr, $cmp:tt all $($rhss:expr),*) => {
match $lhs { _lhs => {
true && $( cmp!(#as_expr _lhs $cmp $rhss) ) && *
}}
};
}
fn main() {
let value = 2;
if cmp!(value, == any 1, 2, 3) {
println!("true! value: {:?}", value);
}
if cmp!(value*2, != all 5, 7, 1<<7 - 1) {
println!("true! value: {:?}", value);
}
}

First off, if your a, b, and c are concrete values, you can just use match:
fn main() {
let x = 42;
match x {
1 | 2 | 3 => println!("foo"),
42 => println!("bar"),
_ => println!("nope"),
}
}
If you want to match on variables you need to write the match arms like this:
match x {
x if x == a || x == b || x == c => println!("foo"),
42 => println!("bar"),
_ => println!("nope"),
}
…which is basically what you want to avoid.
But: A pretty direct translation of your C macro is also possible!
macro_rules! elem {
($val:expr, $($var:expr),*) => {
$($val == $var)||*
}
}
fn main() {
let y = 42;
let x = 42;
if elem!(x, 1, 3, y) {
println!("{}", x);
}
}

I'm partial to writing this without a macro, taking advantage of contains on arrays.
fn main() {
if [1, 2, 3, 4].contains(&4) {
println!("OK");
}
}
It's hard to predict what will happen to this when optimized, but if absolute performance is a goal you'd do well to benchmark each approach.

Yes this is possible, the following macro expands to do each check.
macro_rules! elem {
($n:expr, $( $hs:expr ),*) => ($( $n == $hs )||* );
}
fn main() {
if elem!(4, 1, 2, 3, 4) {
println!("OK");
}
}
Thanks to #vfs on #rust in IRC.

Related

How to create custom operator from a pipe of operators in IxJS?

In rxjs6, we can create an operator from a pipe of operators.
import { pipe } from 'rxjs';
function doSomething() {
return pipe(
map(...),
flatMap(...),
);
}
$.pipe(
map(...),
doSomething(),
flatMap(...),
)
Is there a way to create an operator like this in IxJS?
You can combine operators manually:
import { IterableX as Iterable } from 'ix/iterable';
import { map, filter } from 'ix/iterable/pipe/index';
function customOperator() {
return source$ => map(x => x * x)(
filter(x => x % 2 === 0)
(source$)
);
}
const results = Iterable.of(1, 2, 3, 4).pipe(
customOperator()
).forEach(x => console.log(`Next ${x}`));
Or write your own pipe implementation:
const pipe = (...fns) =>
source$ => fns.reduce(
(acc, fn) => fn(acc),
source$
);
function customOperator() {
return pipe(
filter(x => x % 2 === 0),
map(x => x * x)
)
}

Use output of macro as parameter for another macro

I am trying to implement a generic Point<T> type for small dimensions.
To achieve that, I wrote a macro that takes the name of the new type and the dimension of the point (since, as far as I know, Rust doesn't allow for numerical generics).
macro_rules! define_point {
($type_name: ident, $dimension: expr) => {
pub struct $type_name<T> {
coords: [T; $dimension]
}
}
}
I use it like this:
define_point!(Point2, 2);
define_point!(Point3, 3);
This works fine. I also implement the Index trait on my Point type in this macro to access the coordinates directly.
Now I want some convenience functions for accessing the coordinates of my point as follows: p.x(), p.y() or p.z() depending on the dimension.
To do that, I have another macro:
macro_rules! impl_point_accessors {
($type_name: ident, $coord_name: ident, $coord_index: expr) => {
impl<T> $type_name<T> {
pub fn $coord_name(&self) -> T {
&self[$coord_index]
}
}
};
($type_name: ident, $coord_name: ident, $coord_index: expr, $($extra_coord_name: ident, $extra_coord_index: expr),+) => {
impl_point_accessors!($type_name, $coord_name, $coord_index);
impl_point_accessors!($type_name, $($extra_coord_name, $extra_coord_index), +);
}
}
I use it as follows:
impl_point_accessors!(Point2, x, 0, y, 1);
impl_point_accessors!(Point3, x, 0, y, 1, z, 2);
This seems to work when I look at the result of rustc --pretty=expanded.
Now, as an exercise, I wrote this other macro that would give me the list x, 0, y, 1, ... from the dimension directly:
macro_rules! dimension_to_coord_pairs {
(1) => {
x, 0
};
(2) => {
x, 0, y, 1
};
(3) => {
x, 0, y, 1, z, 2
};
(4) => {
x, 0, y, 1, z, 2, w, 3
};
}
However, when I try to use the output of this new macro like this:
impl_point_accessors!($type_name, dimension_to_coord_pairs!($dimension));
It looks like the dimension_to_coord_pairs macro does not get expanded into the list of arguments that I want.
My question now: Is there any way to tell Rust to expand the macro and use the expanded syntax as my list of arguments in another macro ?
A macro can invoke another macro, but one cannot take the result of another. Each macro invocation must result in legal code, which can include other macro invocations, but the compiler should never have to figure out which macro you intended to be invoked first.
You can work around your problem by reorganising the macros to be completely top-down, something like this:
macro_rules! define_point {
($type_name: ident, $dimension: tt) => {
pub struct $type_name<T> {
coords: [T; $dimension]
}
impl_point_accessors!($type_name, $dimension);
}
}
macro_rules! impl_point_accessors {
($type_name: ident, $dimension: tt) => {
impl<T> $type_name<T> {
write_coord_getters!($dimension);
}
};
}
macro_rules! coord_getter {
($coord_name: ident, $coord_index: expr, $ret: ty) => {
pub fn $coord_name(&self) -> &T {
&self.coords[$coord_index]
}
}
}
macro_rules! write_coord_getters {
(1) => {
coord_getter!(x, 1, T);
};
(2) => {
write_coord_getters!(1);
coord_getter!(y, 2, T);
};
(3) => {
write_coord_getters!(2);
coord_getter!(z, 3, T);
};
(4) => {
write_coord_getters!(3);
coord_getter!(w, 4, T);
};
}
It's not quite as tidy as you were attempting, but it still lets you invoke it the way you wanted:
define_point!(Point3, 3);
Notice that I changed $dimension: expr to $dimension: tt. I'm not 100% sure why this is the case but, inside a macro, a variable of type expr cannot match a literal.
Also, I changed the return type to &T instead of T. You could also fix the same problem by making T: Copy instead.
My question now: Is there any way to tell Rust to expand the macro and use the expanded syntax as my list of arguments in another macro ?
No. Macros are syntactic, not lexical. That is, a macro cannot expand to an arbitrary bundle of tokens. Even if it could, you would need some way to force the compiler to expand the inner macro before the outer one, and you can't do that either.
The closest you can get is to use a "callback" style:
macro_rules! impl_point_accessors {
($type_name: ident, $coord_name: ident, $coord_index: expr) => {
impl<T> $type_name<T> {
pub fn $coord_name(&self) -> T {
panic!("coord {}", $coord_index);
}
}
};
($type_name: ident, $coord_name: ident, $coord_index: expr, $($extra_coord_name: ident, $extra_coord_index: expr),+) => {
impl_point_accessors!($type_name, $coord_name, $coord_index);
impl_point_accessors!($type_name, $($extra_coord_name, $extra_coord_index), +);
}
}
macro_rules! dimension_to_coord_pairs {
(1, then $cb:ident!($($cb_args:tt)*)) => {
$cb!($($cb_args)* x, 0);
};
(2, then $cb:ident!($($cb_args:tt)*)) => {
$cb!($($cb_args)* x, 0, y, 1);
};
(3, then $cb:ident!($($cb_args:tt)*)) => {
$cb!($($cb_args)* x, 0, y, 1, z, 2);
};
(4, then $cb:ident!($($cb_args:tt)*)) => {
$cb!($($cb_args)* x, 0, y, 1, z, 2, w, 3);
};
}
struct Point<T>(Vec<T>);
dimension_to_coord_pairs!(2, then impl_point_accessors!(Point,));

Why underline not work in some scenario of monad?

Underline _ cannot work for some scenario in following code:
case class Item
(
para: Int
)
val a = List(1, 2)
val b = List(Item(1), Item(2))
a foreach {
perA => println(perA * 2) // Line A: ok
}
a foreach {
println(_) // Line B: ok
}
a foreach {
println(_ * 2) // Line C: not ok
}
b foreach {
perB => println(perB.para) // line D: ok
}
b foreach {
println(_.para) // line E: not ok
}
Could someone explain for me about line C & line E, thanks.
TL;DR: the argument of the lambda can be inserted at an unexpected position. Instead of taking
a foreach { println(_.blah) }
and building
a foreach { x => println(x.blah) }
out of it, the compiler instead builds
a foreach { println( x => x.blah ) }
and then fails to derive the type for the argument x.
A) This is the most explicit way to write down the lambda, the only way to make it clearer would be to add a type:
a foreach { perA => println(perA * 2) }
is the same as
a foreach { (x: Int) => println(x * 2) }
This should obviously work.
B) This works because it's one way to write down the function automatically generated from println. It is equivalent to any of the six variants below:
a foreach { (x: Int) => println(x) }
a foreach { x => println(x) }
a foreach { println(_) }
a foreach { println _ }
a foreach { println }
a foreach println
C) Because of the * 2, this here
a foreach { println(_ * 2) }
can no longer be considered just println(_). Instead, it is interpreted as
a foreach { println( { (x: ??!) => x * 2 } ) }
and since println takes no function-valued arguments, it cannot determine what the type of x is supposed to be, and exits with an error.
D) Is essentially the same as A, it works, I hope it's clear.
E) Is a variation of C, but this time, the type-checker isn't looking for something with method *(i: Int), but instead it's looking for something with a member para.
This here:
b foreach { println(_.para) }
is again interpreted as a foreach with a function which ignores elements of b and returns the constant value of the expression println(_.para),
that is:
b foreach { println( { (x: ??!) => x.para } ) }
Again, the inner expression println( { (x: ??!) => x.para } ) does not make any sense, because println does not expect function-valued arguments (it can handle Any, but it's not enough to derive the type of x).

Can macros match against constant arguments instead of literals?

Given the macro matching example, this shows how macros can match an argument.
I've made very minor changes here to use numbers:
macro_rules! foo {
(0 => $e:expr) => (println!("mode X: {}", $e));
(1 => $e:expr) => (println!("mode Y: {}", $e));
}
fn main() {
foo!(1 => 3);
}
Works, printing: mode Y: 3
However I would like to use a constant as an argument, can this be made to work:
const CONST: usize = 1;
macro_rules! foo {
(0 => $e:expr) => (println!("mode X: {}", $e));
(1 => $e:expr) => (println!("mode Y: {}", $e));
}
fn main() {
foo!(CONST => 3);
}
Is this possible in Rust?
Note, using a regular match statement isn't usable for me, since in my code each branch resolves to different types, giving an error.
So I'm specifically interested to know if a constant can be passed to a macro.
No.
Macros operate on the Abstract Syntax Tree, so they reason at the syntactic level: they reason about tokens and their spelling.
For example:
fn main() {
let v = 3;
}
In this case, the AST will look something like:
fn main
\_ let-binding v
\_ literal 3
If you ask a macro whether v is 3, it will look at you funny, and wonder why you would try comparing a variable name and a literal.
I'm fairly sure the answer is "no"; at macro expansion time all you have are token trees - expansion happens before evaluation, or even type inference/checking.
const CONST: usize = 0;
macro_rules! foo {
($i:ident => $e:expr) => {
if $i == 0 {
println!("mode X: {}", $e);
} else if $i == 1 {
println!("mode Y: {}", $e);
}
};
}
fn main() {
foo!(CONST => 3);
}
If you want use identifier in macro it needs to be ident tag and you can use if, else if blocks instead of match.

What is Scala way of finding whether all the elements of an Array has same length?

I am new to Scala and but very old to Java and had some understanding working with FP languages like "Haskell".
Here I am wondering how to implement this using Scala. There is a list of elements in an array all of them are strings and I just want to know if there is a way I can do this in Scala in a FP way. Here is my current version which works...
def checkLength(vals: Array[String]): Boolean = {
var len = -1
for(x <- conts){
if(len < 0)
len = x.length()
else{
if (x.length() != len)
return false
else
len = x.length()
}
}
return true;
}
And I am pretty sure there is a better way of doing this in Scala/FP...
list.forall( str => str.size == list(0).size )
Edit: Here's a definition that's as general as possilbe and also allows to check whether a property other than length is the same for all elements:
def allElementsTheSame[T,U](f: T => U)(list: Seq[T]) = {
val first: Option[U] = list.headOption.map( f(_) )
list.forall( f(_) == first.get ) //safe to use get here!
}
type HasSize = { val size: Int }
val checkLength = allElementsTheSame((x: HasSize) => x.size)_
checkLength(Array( "123", "456") )
checkLength(List( List(1,2), List(3,4) ))
Since everyone seems to be so creative, I'll be creative too. :-)
def checkLength(vals: Array[String]): Boolean = vals.map(_.length).removeDuplicates.size <= 1
Mind you, removeDuplicates will likely be named distinct on Scala 2.8.
Tip: Use forall to determine whether all elements in the collection do satisfy a certain predicate (e.g. equality of length).
If you know that your lists are always non-empty, a straight forall works well. If you don't, it's easy to add that in:
list match {
case x :: rest => rest forall (_.size == x.size)
case _ => true
}
Now lists of length zero return true instead of throwing exceptions.
list.groupBy{_.length}.size == 1
You convert the list into a map of groups of equal length strings. If all the strings have the same length, then the map will hold only one such group.
The nice thing with this solution is that you don't need to know anything about the length of the strings, and don't need to comapre them to, say, the first string. It works well on an empty string, in which case it returns false (if that's what you want..)
Here's another approach:
def check(list:List[String]) = list.foldLeft(true)(_ && list.head.length == _.length)
Just my €0.02
def allElementsEval[T, U](f: T => U)(xs: Iterable[T]) =
if (xs.isEmpty) true
else {
val first = f(xs.head)
xs forall { f(_) == first }
}
This works with any Iterable, evaluates f the minimum number of times possible, and while the block can't be curried, the type inferencer can infer the block parameter type.
"allElementsEval" should "return true for an empty Iterable" in {
allElementsEval(List[String]()){ x => x.size } should be (true)
}
it should "eval the function at each item" in {
allElementsEval(List("aa", "bb", "cc")) { x => x.size } should be (true)
allElementsEval(List("aa", "bb", "ccc")) { x => x.size } should be (false)
}
it should "work on Vector and Array as well" in {
allElementsEval(Vector("aa", "bb", "cc")) { x => x.size } should be (true)
allElementsEval(Vector("aa", "bb", "ccc")) { x => x.size } should be (false)
allElementsEval(Array("aa", "bb", "cc")) { x => x.size } should be (true)
allElementsEval(Array("aa", "bb", "ccc")) { x => x.size } should be (false)
}
It's just a shame that head :: tail pattern matching fails so insidiously for Iterables.