Rust lang series episode #21 — macros (#rust-series)

in rust-series •  8 years ago  (edited)

Hello everyone, new episode of rust series is here. Today it's going to be some introduction of Rust macros. Macros in Rust bring even more flexibility to Rust language. We already know many macros like println!, vec! and some others. When you see something ending with exclamation mark in rust you can be quite sure it's a macro. It mostly means that it has special syntax and special features which are out of scope of standard function syntax.

Macros has some advantages and some disadvantages:

  • advantages: richer syntax, features
  • disadvantages: harder to read, harder to write

Standard library macros

There are various macros that we are commonly using

  • panic! - causes current thread to panic (panic!("unexpected state!");)
  • vec! - macro for creating vectors (let v = vec![1,2,3];)
  • try! - macro that takes Result<T,E> and either gives Ok value or returns error out from enclosing function
  • assert! - basic assertion (assert!(result_below_ten < 10);)
  • assert_eq! - basic equality assertion (assert!(result_zero_expected, 0);)
  • unreachable! - macro suited for unreachable code (unreachable!();)
  • unimplemented! - for code that is not yet implemented (unimplemented!());

Creating own macros

Creating macro stars with calling macro_rules! ... ehm macro :).

Simple macro

Let's write simple echo macro. You can object that for this we don't need macro at all and you're right. But it illustrates basic syntax.

macro_rules! echo {
  ($x:expr) => {
    println!("Call:{}", $x);
    println!("Echo:{}", $x);
  }
}

fn main() {
  echo!("Halooo Steemit!");
}

# output
Call:Halloo Seemit!
Echo:Halloo Steemit!

$x:expr here is any Rust expression, $x is meta variable. Then "=>" referes to block where meta variables can be used.

Multiple values

We can also have multiple optional parameters (which normal function cannot accept). Then we use special expression:

macro_rules! multilines {
    ( $( $x:expr ),* ) => {
        {
            $(
                println!($x);
            )*
        }
    };
}


fn main() {
  multlines!("first line","second line","third line");
}

# output
first line
second line
third line

$(...),* means zero or more expressions
$(...),+ means one or more expressions

Macro matching parameters

It's also possible to construct macro that can match input parameter. Check this code

macro_rules! macro_xy {
    (x => $e:expr) => (println!("x matched, value = {}", $e));
    (y => $e:expr) => (println!("y matched, value = {}", $e));
}

fn main() {
    macro_xy!(x => 4);
    macro_xy!(y => 5);
}

# output
x matched, value = 4
y matched, value = 5

There is much more to macros but these basic should illustrate enough how they are written and should be easier to write more complex constructions.

Postfix

That's all for now, thank you for your appreciations, feel free to comment and point out possible mistakes (first 24 hours works the best but any time is fine). May Jesus bless your programming skills, use them wisely and see you next time.

Meanwhile, you can also check the official documentation to know more about writing macros

#rust-series
#rust-lang
#rust

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!