Create when statment with macros

Hi everybody. I wonder if there is some possibility to create a macro that simplify the if/else if branches like the when statement in Kotlin (https://kotlinlang.org/docs/reference/control-flow.html).

Something like:

let x = 0;
let positive = when! {
    x >= 0 => true,
    x < 0 => false
};

The purpose is to simplify complex if/else if branches like:

when! {
  coord.v < 250 => 0,
  coord.h <= leftLimit.h && hSpeed <= 20 => -10,
  coord.h >= rightLimit.h && hSpeed >= -20 => 10,
  hSpeed < -40 => -60,
  hSpeed > 40 => 60,
  coord.h >= leftLimit.h + 5 && coord.h <= rightLimit.h - 5) => {
    when! {
      hSpeed < -30 => -60,
      hSpeed > 30 => 60,
      hSpeed < 0 => -10,
      hSpeed > 0 => 10,
      else => 0
    }
  },
  else => 0
}

Thank’s

Doesn’t the match { ... if ... } syntax satisfy your needs? Your first example would be as such:

let x = 0;
let positive = match x {
    _ if x >= 0 => true,
    _ if x < 0 => false,
    // the last part is essentially the "else" case
    _ => panic!("Something really weird happened")
};

Second example would be more complicated, of course, but also very close to your one.

2 Likes

Range patterns and match guards cover a lot of use cases. See here for more information.

1 Like

Thank you for both responses I didn’t see the part of the documentation.

Here’s an ok version: https://play.rust-lang.org/?gist=e462d19f41d5215a07fa17af94a65316

macro_rules! when {
    ( $($e:expr => $v:expr,)* else $w:expr ) => {
        match () {
            $(() if $e => $v,)*
            _ => $w,
        }
    }
}

fn main() {
    let x = 0;
    let signum = when! {
        x > 0 => 1,
        x < 0 => -1,
        else 0
    };
    println!("{:?}", signum);
}

But definitely prefer patterns and guards where convenient.

1 Like