# Idea: Empy designator could reduce macro recursion

**URL:** <https://internals.rust-lang.org/t/idea-empy-designator-could-reduce-macro-recursion/10339>\
**Category:** language design\
**Created:** [June 3, 2019, 10:55am UTC](https://internals.rust-lang.org/t/idea-empy-designator-could-reduce-macro-recursion/10339 "2019-06-03T10:55:44Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![adamAndMath](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/adamandmath/32/5752_2.png) [@adamAndMath](https://internals.rust-lang.org/u/adamAndMath)\
**Post date:** [June 3, 2019, 10:55am UTC](https://internals.rust-lang.org/t/idea-empy-designator-could-reduce-macro-recursion/10339/1 "2019-06-03T10:55:44Z")

</div>

I’ve been looking at macro\_rules macros, and I’ve seen many people writing extremely recursive macros. This often comes at a significant cost of readability and maintenance of such macros. It can also require increasing the `recursion_limit`.

My idea is to introduce an `empty` designator to keep track of repetition, when the repeated part does not contain a meta variable. This would be written as `$tracker:empty`.

A simple example of a macro that would benefit from this, would be a counting macro such as this:

```rust
macro_rules! count {
    () => (0);
    (+$($rest:tt)*) => (count!($($rest)*)+1);
    (-$($rest:tt)*) => (count!($($rest)*)-1);
}

```

Using an empty meta variable, it could instead be written as:

```rust
macro_rules! count {
    ($($start:empty+)*$($sub:empty-$($add:empty+)*)*) => {
        0+$($start+1)*$($sub-1$($add+1)*)*
    };
}

```

Adding an empty designator to rust should not be a complex addition to the language, as there already exists designators, such as `vis`, that accept no tokens.

---

<div class="post-metadata">

**Author:** ![dhm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dhm/32/4879_2.png) [@dhm](https://internals.rust-lang.org/u/dhm)\
**Post date:** [June 3, 2019, 12:34pm UTC](https://internals.rust-lang.org/t/idea-empy-designator-could-reduce-macro-recursion/10339/2 "2019-06-03T12:34:14Z")

</div>

So, if I have understood it correctly, you mean to catch patterns such as `$(+)?` with a name, your proposed syntax for it being `$name:empty+`, is that it?

In that case, I like the idea, but I would personally prefer a syntax more akin to `$name(+)?` (allowing to catch an optional pattern made of more than 1 token, specially consistent with an expansion of `$name(+ 1)?`). Remains to see if it is / can be (made) backwards-compatible.

By the way, the example you have given would still lead to ambiguous parsing (even if all the parsing choices lead to the same result):

- [Proof](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=7234f44df867af3f81847daf6e1b2af1)

---

<div class="post-metadata">

**Author:** ![adamAndMath](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/adamandmath/32/5752_2.png) [@adamAndMath](https://internals.rust-lang.org/u/adamAndMath)\
**Post date:** [June 3, 2019, 12:44pm UTC](https://internals.rust-lang.org/t/idea-empy-designator-could-reduce-macro-recursion/10339/3 "2019-06-03T12:44:16Z")

</div>

Not quite. I’m proposing keeping track of repetitions such as `$(abc)?`, `$(abc)*` and `$(abc)+` by inserting a metavariable that accepts the empty string and only the empty string. As such these repetitions would become `(abc$tracker:empty)?`, `(abc$tracker:empty)*` and `(abc$tracker:empty)+`. As such the translation would be [this](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=e54fcc26a3ee66f48998f6fa1efef0c4), which is not ambiguous

---

<div class="post-metadata">

**Author:** ![dhm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dhm/32/4879_2.png) [@dhm](https://internals.rust-lang.org/u/dhm)\
**Post date:** [June 3, 2019, 12:49pm UTC](https://internals.rust-lang.org/t/idea-empy-designator-could-reduce-macro-recursion/10339/4 "2019-06-03T12:49:22Z")

</div>

Ohh, I see, I had indeed gotten it wrong. I wasn’t too far off, though, since the purpose of the empty designator seems to be about being able to mention “constant tokens” using a metavariable.

Hence the possibility for the `$name(...)¤` (with any of the three Kleene operators instead of `¤`).

I am fine with either form, and if it can be done (retro-compat yadda yadda), it is indeed a clever hack to replace some recursions by repetitions 🙂

---

<div class="post-metadata">

**Author:** ![adamAndMath](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/adamandmath/32/5752_2.png) [@adamAndMath](https://internals.rust-lang.org/u/adamAndMath)\
**Post date:** [June 3, 2019, 12:55pm UTC](https://internals.rust-lang.org/t/idea-empy-designator-could-reduce-macro-recursion/10339/5 "2019-06-03T12:55:30Z")

</div>

I agree that that is a much more elegant solution, but my suggestion was meant to be a minimal change. I don’t know my way around the compiler yet, but it seems quite trivial to add an empty designator

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [June 3, 2019, 3:24pm UTC](https://internals.rust-lang.org/t/idea-empy-designator-could-reduce-macro-recursion/10339/6 "2019-06-03T15:24:20Z")

</div>

(member of wg-grammar, speaking as me, not for the wg)

I think the best macro\_rules matching grammar for this (matching a whole repetition) would be `$name:()¤`.

`$name()?` (`missing_fragment_specifier`) is [currently a deny-by-default future-compat lint on declaration](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=7c3808deb0b32c08fc91548017995279) and error on use ([#40107](https://github.com/rust-lang/rust/issues/40107)).

By adding the `:`, we effectively make the `()¤` token trees the fragment specifier as what `$name` is matching.

The problem remains as to what the use syntax should be. There’s no option that “attaches” a block to the matcher expansion without breaking backwards compat or making the `macro_rules` grammar data dependent (i.e. parse depends on macro fragment types). `$name()?` _has_ to continue to work as a matched ident fn call and try. I’d lean towards the matcher just expanding to every tt matched, as do other macro matchers with their respective hygenic AST node.

An `empty` fragment specifier is a powerful tool for little complexity, and iiuc actually covers any use cases for a repetition matcher (though said matcher might be more elegant).

---

<div class="post-metadata">

**Author:** ![adamAndMath](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/adamandmath/32/5752_2.png) [@adamAndMath](https://internals.rust-lang.org/u/adamAndMath)\
**Post date:** [June 6, 2019, 9:37pm UTC](https://internals.rust-lang.org/t/idea-empy-designator-could-reduce-macro-recursion/10339/7 "2019-06-06T21:37:30Z")

</div>

I’ve stumbled upon a case where naming repetition is more powerful than an empty designator. Naming repetitions directly allow you to combine different separately repeating parts:

```rust
macro_rules! {
    ($i:($Name:ident),+;$j:($Par:ty),+) => {
        $i:(struct $Name($j($Par),+);)+
    };
}

```

As an empty designator wouldn’t allow you to specify what to repeat when, this example would still be ambiguous.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [September 4, 2019, 9:45pm UTC](https://internals.rust-lang.org/t/idea-empy-designator-could-reduce-macro-recursion/10339/8 "2019-09-04T21:45:20Z")

</div>

Closed on September 4, 2019, 9:45pm UTC

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
