[DSP] Rust macros love

This is a part of my Daj się poznać / Get Noticed! 2017 series. It is for a contest where I have to write a blog post twice a week abd create a open source project. Read more about it here.

When I evaluated Rust as a language of choice, I didn’t really look into its macro capabilities. And that’s a shame, because it’s really worth mentioning.

Macros, for me, are a double-bladed sword - they bring a lot of power to the language, but can also render your code completely unreadable. The example of first one is Elixir, where you can do crazy things with macros that make coding much more pleasant. “Bad macros” are in C++ or VB.

In Rust, they can save you a lot of writing.

I met them while I pulled clap library into my project. It’s a cargo package for handling command line options for your application. It’s similar to many tools available in other technologies in terms of logic. But take this snippet from my current code:

let matches = clap_app!(bletchley =>
    (version: "0.1")
    (author: "Paweł Świątkowski")
    (@subcommand gen =>
        (about: "Generates keys")
        (@arg name: -n --name +takes_value "Base of the filenames of created keys (default: \"id\")")
    )
    (@subcommand encrypt =>
        (@arg key: -k --key +takes_value +required "key to encrypt with")
        (@arg FILE: +required)
    )
).get_matches();

This is example of config using macros. It’s counterpart with “true” Rust code would be:

let matches = App::new("bletchley")
  .version("0.1")
  .author("Paweł Świątkowski")
  .subcommand(SubCommand::with_name("gen")
    .about("Generate keys")
    .arg(Arg::with_name("name")
      .short("n")
      .takes_value(true)
      .help("Base of the filenames of created keys (default: \"id\")")
    )
  )
  .subcommand(SubCommand::with_name("encrypt")
    .arg(Arg::with_name("key")
      .short("k")
      .takes_value(true)
      .required(true)
      .help("key to encrypt with")
    )
    .arg(Arg::with_name("FILE")
      .required(true)
    )
  )
.get_matches();

So, the “full code” is not so bad, however I think that it’s pretty obvious that macro version is much more concise and readable. And performance should be just the same.

How to write macros? For now it’s a bit too difficult for me. Maybe later. But as everything with Rust, there is an excellent tutorial available.

Related posts