Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Metavariables in macro def #121

Open
topecongiro opened this issue Mar 30, 2018 · 4 comments
Open

Metavariables in macro def #121

topecongiro opened this issue Mar 30, 2018 · 4 comments

Comments

@topecongiro
Copy link

Recently rustfmt started to format macro def.

Should rustfmt add a space after : of metavariables? Adding a space is consistent with other items like function or type declaration. However majority of the code in the wild seems to use the no-space style.

/// Add a space after `:`
macro_rules! foo {
    ($x: ident, $y: ident, $z: ident) => {};
}

/// No space after `:`
macro_rules! foo {
    ($x:ident, $y:ident, $z:ident) => {};
}

Also what should we do when metavariables are separated by separators other than ,, especially by :?

/// Add a space after `:`
macro_rules! foo {
    ($x: ident : $y: ident : $z: ident) => {};
}

/// No space after `:`
macro_rules! foo {
    ($x:ident : $y:ident : $z:ident) => {};
}
@strega-nil
Copy link

Metavariables were discussed back in the day in the style team - we agreed on $name:kind, because of examples like your second one.

@petrochenkov
Copy link

Repeating what I said in rust-lang/rustfmt#2534 (comment), macros should be formatted like normal code, i.e. with space in $name: kind and possibly an extra preceding space when : is used as a separator ($x: ident : $y: ident).

@nrc
Copy link
Member

nrc commented Apr 12, 2018

I can't find any discussion of macros in this repo and I don't recall coming to the conclusion in #121 (comment), however, it is perfectly possible that we did - it was a long time ago. In the current guide, we don't have any discussion on macro defintions, and since they can be arbitrary tokens I'm not sure we even can give good guidance.

I do agree with @petrochenkov that we should make macros look like functions (since they are very similar in the common case). However, the no space pattern is common in the ecosystem and certainly looks better when :s are also used elsewhere.

@ghost
Copy link

ghost commented Apr 13, 2018

@nrc

I do agree with @petrochenkov that we should make macros look like functions (since they are very similar in the common case).

There are a few interesting differences:

  1. Arguments to functions are comma-separated lists of patterns and types, while arguments to macros are just lists of tokens (separated by spaces only).
  2. Patterns and types in functions can be long and complicated (e.g. mut foo: &'a Rc<RefCell<My<'b, String>>>), while token names and types in macros are always simply dollar-word-colon-word (e.g. $foo:ident).

It's important to note that in macros commas are tokens, too.

Consider this: $foo: tt, $bar: ident. There are actually three tokens at play here:

$foo: tt, $bar: ident
^^^^^^^^
        ^
          ^^^^^^^^^^^

I find it a little difficult to skim through this token list and visually figure out what is a token and what is a type. The following formatting is easier to follow for me:

$foo:tt , $bar:ident

Finally, separators are visually lightweight so I'm okay with gluing the comma to the first token:

$foo:tt, $bar:ident

Lately I've been working with macros a lot and found that I read function signatures and macro patterns differently:

  • In function signatures, I focus on types only. Patterns (variable names) are often less important. That's why in Haskell signatures like length :: [a] -> Int read so well.

  • In macro patterns it's the opposite. I focus on patterns only and ignore the token types. For example, when reading [$i:expr] recv($r:expr, $m:pat) => $body:tt, $($tail:tt)* my mind just skips over the token types and focuses on the structure of the pattern and token names instead (i is index, r is receiver, m is message).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants