macro_rules! cascade {
    (let _ : $t:ty = $e: expr; $($tail: tt)*) => { ... };
    (let $i:ident : $t:ty = $e: expr; $($tail: tt)*) => { ... };
    (let $i:ident = $e: expr; $($tail: tt)*) => { ... };
    ($e: expr; $($tail: tt)*) => { ... };
    (@line $i: ident, .. $v: ident = $e: expr; $($tail: tt)*) => { ... };
    (@line $i:ident, .. $v:ident += $e:expr; $($tail:tt)*) => { ... };
    (@line $i:ident, .. $v:ident -= $e:expr; $($tail:tt)*) => { ... };
    (@line $i:ident, .. $v:ident *= $e:expr; $($tail:tt)*) => { ... };
    (@line $i:ident, .. $($q: ident ($($e: expr),*)).+; $($tail: tt)*) => { ... };
    (@line $i:ident, .. $($q: ident ($($e: expr),*)).+?; $($tail: tt)*) => { ... };
    (@line $i:ident, { $($t:tt)* }; $($tail: tt)*) => { ... };
    (@line $i:ident, $s: stmt; $($tail: tt)*) => { ... };
    (@line $i:ident, { $($t:tt)* }) => { ... };
    (@line $i:ident, .. $($q: ident ($($e: expr),*)).+) => { ... };
    (@line $i:ident, $e:expr) => { ... };
    (@line $i:ident,) => { ... };
    () => { ... };
}
Expand description

A macro for chaining together statements that act on an initial expression.

Usage

Cascading allows you to run multiple statements on a struct generated by an expression without having to repeatedly type it out. This can be very convinient for modifying multiple properties simultaneously, or running a long series of individual methods on a struct.

When writing a cascade, the first line specifies the expression that will be operated upon. All following lines modify the struct created by the expression in some way. The most common operator is the .. member operator, which is borrowed from Dart’s syntax. It’s a convinient shorthand for accessing a member or method of the struct. For example:

use cascade::cascade;

let old_vector = vec!(1, 2, 3);
let new_vector = cascade! {
  old_vector;
  ..push(4);
  ..push(5);
  ..push(6);
};

Remember, you can’t move the struct, because it gets returned at the end of the cascade. In other words, you can’t run a method on a struct with the .. operator if the method takes self or mut self. But &self or &mut self works fine.

You can also put statements without a .. in a cascade macro:

use cascade::cascade;
use std::collections::HashMap;

let hash_map = cascade! {
  HashMap::new();
  ..insert("foo", "bar");
  println!("Look! You can put statements in a cascade!");
  for i in 0..3 {
    println!("You can put loops in here too! Make sure to put a semicolon at the end!");
  };
};

If you need to reference the expression inside a cascade, you can name it using let:

use cascade::cascade;

let vector = cascade! {
  let v = Vec::new();
  ..push(1);
  println!("The vector now has {} element(s).", v.len());
  ..push(2);
};

This will print The vector now has 1 element(s).

Once again, trying to move this value will throw an error.

Finally, you can also use the member operator (..) to set or change members of the cascaded struct:

use cascade::cascade;
struct A {
  pub b: u32,
  pub c: u32
}

let a = cascade! {
  A { b: 0, c: 0 };
  ..b = 5;
  ..c += 1;
};

More examples of the cascade macro can be found in the examples folder on the Github repository.