dry — Don't Repeat Yourself

Latest version Documentation License: MIT/Apache 2.0

Rust macros for idiomatic deduplication of code. Use whenever macro_rules! are too powerful and clunky.

toml [dependencies] dry = "0.1.1"

Usage

macro_for!

You know the trusty for loop:

rust for number in [1, 2, 3, 4, 5] { println!("{}", number); }

Use macro_for! to iterate over tokens at compile time:

rust macro_for!($Struct in [A, B, C, D, E] { struct $Struct { many_fields: bool, so_many_fields: bool, impossibly_many_fields: bool, } });

Compared to using macro_rules!:

rust macro_rules! my_struct { ($Struct:ident) => { struct $Struct { many_fields: bool, so_many_fields: bool, impossibly_many_fields: bool, } }; } my_struct!(A); my_struct!(B); my_struct!(C); my_struct!(D); my_struct!(E);

See the examples for more details.

macro_wrap!

Allows you to use the other macros in this crate in places where macro invocations are illegal (e.g. struct fields, enum cases, match arms).

Wrap the closest syntax tree ancestor that is in a macro invocation position and you're good to go:

rust macro_wrap!(match x { // ↓ can't usually call macros here, but `macro_wrap!` makes it work macro_for!($Variant in [A, B, C, D, E] { Enum::$Variant => 1, }) })

Features

The nightly feature (disabled by default) enables functionality that uses the unstable [proc_macro_span] rustc feature. It enables better syntax checking (disallows spaces between the "$" and the substitution variable names) and emits more source code hints on errors (though quick-fixes for macros aren't available even on nightly yet).

If you're running Rust nightly, you can enable it:

toml [dependencies] dry = { version = "0.1.1", features = ["nightly"] }

About This Crate

Dependencies

The only dependency is [proc-macro-error], for those sweet, sweet, friendly error messages across Rust versions. In turn, it depends on [quote] and [proc-macro2]. However, we don't depend on [syn] at all so dry should be really light on compile times.

Caution

You should try to use an abstraction like looping, traits, or generics if at all possible. But when it's not, dry makes it as painless and pleasant as possible to avoid repeating yourself.

Prior Art

For Each Loops

All of them use bare identifiers instead of "$"-prefixed identifiers like dry and macro_rules! do, which make it clear when macros are being used versus standard language features within the loop body. None of them support replicating struct fields, enum cases, or match arms as far as I'm aware.

N Repetitions

License

dry is licensed under the MIT License and the Apache 2.0 License, at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Contributing

Please open a pull request if you'd like to see anything fixed or added, or create an issue if you're not sure how to get started.

Roadmap to 1.0