1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
//! A macro to declare multiple mutable variables in one statement. //! //! `var! { ... }` is a generalised form of `let mut x = ...;`, //! allowing for several mutable variables to be declared and //! initialised at once, inspired by the keyword of the same name in //! languages like Nim and C#. //! //! [Available on crates.io](https://crates.io/crates/var) //! //! # Grammar //! //! ```not_rust //! "var! {" //! ( //! identifier (":" type)? "=" expression //! )* //! "}" //! ``` //! //! where //! //! - `"..."` represents a literal `...` //! - `(...)` is for grouping //! - `*` is zero-or-more copies of the previous entity, *comma separated*, with //! optional trailing comma //! - `?` is zero-or-one copies of the pervious entity (i.e. optional) //! //! Notably, //! //! - `var!` should always be invoked with `{}`s or else one will get //! compile errors (invoking a macro with `()` and `[]` mean the its internals //! are parsed as an expression, but declaring a variable with `let` is a //! statement), //! - an initialising expression is required, unlike conventional `let`, //! - pattern matching cannot be performed. //! //! # Examples //! //! ```rust //! #[macro_use] extern crate var; //! //! fn fibonacci(n: u32) -> u64 { //! var! { //! a: u64 = 0, //! b = 1, //! } //! for _ in 0..n { //! let tmp = a + b; //! a = b; //! b = tmp; //! } //! return a //! } //! //! fn main() { //! assert_eq!(fibonacci(10), 55); //! } //! ``` /// The main macro, see crate docs for details. #[macro_export] macro_rules! var { ($($vals: tt)*) => { __var_internals! {__make_things_work: () = (); $($vals)*,} }; } /// Implementation details. **Do not use this directly.** #[macro_export] macro_rules! __var_internals { ($($name: ident : $t: ty = $init: expr),*; $(,)*) => { let ($(mut $name),* ,): ($($t),* ,) = ($($init),* ,); }; ($($bname: ident : $bt: ty = $binit: expr),*; $name: ident = $init: expr, $($rest: tt)*) => { __var_internals!{$($bname: $bt = $binit,)* $name: _ = $init; $($rest)*} }; ($($bname: ident : $bt: ty = $binit: expr),* ; $name: ident : $t: ty = $init: expr, $($rest: tt)*) => { __var_internals!{$($bname: $bt = $binit,)* $name: $t = $init; $($rest)*} }; }