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

Change attribute syntax to @foo #483

Closed
wants to merge 6 commits into from

Conversation

sfackler
Copy link
Member

As with the enum thing, I can commit to pushing the impl through relatively quickly.

Rendered

@sinistersnare
Copy link

👍 syntax is also used in (at least) Python and Java, and is easy to parse visually.

Thanks @sfackler :D

@pcwalton
Copy link
Contributor

Yeah, I wanna do this.

@ftxqxd
Copy link
Contributor

ftxqxd commented Nov 26, 2014

This should probably mention as a drawback that #[foo] (1 + 1) (pretending that RFC 16 is implemented) would have to be written as @foo { 1 + 1 } instead under this RFC (because @foo (bar) would be parsed as an attribute with one parameter, bar).

I like this idea overall, though. I’ve seen a few newcomers to the language on IRC avoid attributes because they look vaguely like C preprocessor directives. This syntax seems natural to me, has precedent from other languages, and looks nicer than the current weird syntax. 👍

@mcpherrinm
Copy link

I think @foo is a good idea (coming from python/java). But I am not sure about @!foo: Although it matches our current syntax, it is still a little subtle. I wouldn't block on this, but maybe somebody has a better idea?

@steveklabnik
Copy link
Member

I really like this.

@sfackler
Copy link
Member Author

@P1start good point, I added a paragraph. The ambiguity is a bit unfortunate, but I think it'll be a rare enough case in practice that it won't be too much of an issue.

@sfackler
Copy link
Member Author

Hmm, actually, it could cause a real issue for attributes attached to match arms. I don't think there's actually a work around in the currently proposed grammar for this:

match (foo, bar) {
    @thing
    (a, b) => {...}
}

Maybe we should continue optionally allowing [] delimiters for these kinds of cases?

match (foo, bar) {
    @[thing]
    (a, b) => {...}
}

@DanielKeep
Copy link

For what it's worth, I actually like how the current attribute syntax looks. I'd much rather be able to apply them in more positions.

@tomjakubowski
Copy link
Contributor

-1. This makes attaching attributes to expressions annoying, and I find @attr and especially @!attr to be subjectively uglier than the status quo. I don't buy the familiarity argument because Rust attributes are pretty different to me from Python decorators. Can't speak for Java's use of @ though.

Maybe we should continue optionally allowing [] delimiters for these kinds of cases?

FWIW, if this RFC were to go through and this optional syntax were available, I would prefer to always use the [] delimiters because I find it much easier to read this way.

@bstrie
Copy link
Contributor

bstrie commented Nov 26, 2014

Ah! I was planning on writing up this RFC (sorry, @nikomatsakis!), but I was stymied by precisely the syntax ambiguity that you've used [] to disambiguate. However, the solution you've presented here is still ambiguous, given that the following is also legal today:

    let x = [(1i, 2i)];
    match x {
        #[lol]
        [(a, b)] => (),
    }

I would really, really, really like to see this RFC land, but I haven't yet thought of the best way to disambiguate this.

@Valloric
Copy link

👍 Consistency with other languages is good, all other things being equal. Using @ will make the syntax familiar to Rust newcomers.

@sfackler
Copy link
Member Author

@bstrie I don't think that's a problem. []s have to be properly nested, so the parser knows that it's done parsing the attribute when it hits the first ], and it knows it's done parsing attributes in general since the next token isn't a @ (or #).


Note that some attributes which are legal today have no equivalent:

* `#[deprecated = "foo"]` becomes `@deprecated(reason = "foo")`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just @deprecated("foo")?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the alternatives section for that grammar.

@sfackler
Copy link
Member Author

In that case a @lol would work fine as well since the next token isn't a (.

Support for `#[deprecated = "reason"]` style attributes is removed because
`@deprecated = "reason"` is a bit visually confusing since there are no
delimiters wrapping the attribute. There are a couple of alternatives here.
One is to just allow that syntax. It's not grammatically ambiguous, after all.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heartily against this alternative, this form is just noisier and less powerful.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The @deprecated = "reason" alternative or the @deprecated("reason") alternative? I think they're both isomorphic to the current grammar.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, and I'm heartily against the current #[foo = "bar"] form as well, which is why I'm so eager to use this opportunity to nix it from the language. :)

@huonw
Copy link
Member

huonw commented Nov 26, 2014

Maybe we should continue optionally allowing [] delimiters for these kinds of cases?

Or allow @foo().

@DanielKeep
Copy link

@Valloric I think that's a somewhat disingenuous argument; Python lets you define and use a custom function or object. I believe Java lets you attach custom objects to the runtime metadata for introspection purposes. Rust only allows constructs defined by the compiler or standard library; it won't be possible to define these in stable Rust anytime soon.

In addition, insofar as I'm aware, neither Python or Java allow inner attributes, only outer ones.

Oh, and someone coming from D might be forgiven for believing that these are all just regular keywords that happen to have a @ in them.

Also, C# uses [...], so Rust is reasonably consistent with that.

I don't think the consistency argument is very well founded; it's grasping at a relatively minor visual distinction, whilst ignoring deeper semantics. I could make the argument that this is similar to the *T to *const T change that was made, specifically because the familiar, consistent syntax didn't actually do what people might expect it to do.

@sfackler
Copy link
Member Author

Rust only allows constructs defined by the compiler

That isn't true. You can attach whatever you want - it just might not do anything (and warn).

and it won't be possible to define these in stable Rust anytime soon.

I'm hoping to get syntax extensions into the stable language sometime next year.

@sfackler
Copy link
Member Author

@huonw yeah, that's another option. There's a bit of a risk there of syntax extensions messing up because they're looking specifically for a MetaWord(foo) but not a MetaList(foo, vec![]) or vice versa. Might not be worth worrying about - or we could get rid of MetaWord entirely and use MetaList with an empty list.

@huonw
Copy link
Member

huonw commented Nov 26, 2014

@sfackler I think we can solve those implementation details satisfactorily enough for it to not be a worry (e.g. removing MetaWord as you suggest).

@lifthrasiir
Copy link
Contributor

With a new attribute sigil, the inner attribute is horrible to read in my opinion: #![features(globs)] vs. @!features(globs). This is mostly due to the omission of brackets, to be exact, but this RFC made them optional so it is not an unrelated issue. Maybe it's (possibly the last) time to discuss about the inner attribute syntax? The latest discussion at rust-lang/rust#2569 had several ideas but was concluded without a consensus.

@reem
Copy link

reem commented Nov 26, 2014

I would rather have @(foo) than @[foo], personally. I find parens much less jarring than brackets in general.

@sfackler
Copy link
Member Author

@reem Yeah, now that I think about it, I prefer @foo() followed by @(foo) and then @[foo].

@pythonesque
Copy link
Contributor

Yeah, Rust's attributes were inspired by C#'s attributes IIRC.

I have no strong feelings about this landing (I prefer the old syntax but wouldn't mind the new one), but I am deeply skeptical that @foo vs #[foo] has any compelling arguments other than personal preference. The last time we had such a situation was <Foo> vs [Foo] for generics, and that was closed for the same reason.

@netvl
Copy link

netvl commented Nov 26, 2014

-1. Frankly, motivation is less than compelling. It does look like a personal preference. Especially given that there are ambiguities. I'm convinced that drawbacks are much larger than benefits (which I don't even see, beyond similarity to other languages, extent of which is arguable).

@pzol
Copy link

pzol commented Nov 26, 2014

-1 agree that this is just personal preference, I like the current style

@glaebhoerl
Copy link
Contributor

My personal preference is #foo and #bar(baz), sans brackets, though perhaps we could continue to allow brackets for grouping: #[foo, bar(baz)] (which is equivalent to #foo #bar(baz), so it's not really necessary). But I'd be fine with @ as well. It's a somewhat nicer symbol... precisely because it's a nicer symbol, however, it has a lot of possibility as potential syntax for future language features we haven't even thought of yet, whereas # is most likely too ugly to use for anything else. So keeping # for attributes would be a more efficient use of limited ASCII real estate.

@cl91
Copy link

cl91 commented Nov 26, 2014

-1 frankly the arguments for this are not compelling enough to justify the hassle, especially since we now have quite a lot of existing Rust projects and this will break pretty much everyone's code. It seems to be just a personal preference and I failed to see how two less keystrokes will improve the usabiliy/productivity in any fundamental way.

@chris-morgan
Copy link
Member

Those advocating square brackets (single, as in C♯, or double, as in C++) should realise the unavoidable ambiguity with array literals once we get to attributes on expressions. For that reason I think it is fair to say that we simply cannot do just that, as we have declined to have a requirement of arbitrary lookahead to resolve ambiguities.

When it comes to consistency with other languages, our current # has a substantially different meaning from that of the C/C++ preprocessor, for example, which can be assumed to be something people coming to Rust are more likely to be familiar with. That is a slight argument in favour of departing from #, a slightly stronger argument against switching from #[…] to #….

Really, if we week to change our syntax for consistency with other languages, removing any that are not syntactically possible for us to adopt (such as the square brackets of C♯/C++), this @…, as in Python and Java, is the only choice I see.

I feel that going for familiarity and conformity with other languages in this way is of value. 👍.

@chris-morgan
Copy link
Member

I will, however, note that I’m not so comfortable with @!… as the parallel to @… as I was with #![…] as the parallel to #[…]. @!foo reads too much like “not foo”. Perhaps we could consider something like @^… again, though we must of course bear in mind //!.

@michaelwoerister
Copy link
Member

I think this would be a good idea. I like that @ is a good mnemonic for 'attribute' and that we get rid of the square brackets, which I personally find cumbersome to type for attributes. Consistency with Java and Python is also a good argument, I think.

If we are going to do a change like this, I'm strongly in favor of doing it before 1.0

@glaebhoerl
Copy link
Contributor

I like that @ is a good mnemonic for 'attribute'

As far as that goes, # is also a good mnemonic for 'metadata' (hashtags).

@kennytm
Copy link
Member

kennytm commented Nov 26, 2014

👎 Unlike the macro syntax change foo!@foo, this RFC brings no compelling benefit at all, other than "it looks better to me" or "it looks similar to Java/Scala/Python/D/Swift/Dart/etc.". These reason are good if we are introducing new syntax, but these don't convince me to accept a change.

@emk
Copy link

emk commented Nov 26, 2014

A large fraction of my attributes are going to be @!foo, which feels uglier than #![foo]. And C# and C++ both use something based on [] anyway, so Rust is already semi-consistent with two major low-level languages. And then there's the issue with match arms. On the plus side, the new syntax looks better when there are two attributes on a line: @foo @bar is nice, but #[foo] #[bar] makes my fingers twitch towards the Enter key, and I'm not sure why. Overall, purely as a random Rust coder, it doesn't feel like a clear win—more a case of aesthetic preference between two sets of tradeoffs.

I guess if people really want this I don't mind it. But it means going through the whole library update dance. But unlike every other recent change, this basically breaks everybody, so it's going to take a couple of days to track down all the package authors and ask them to upload new versions to crates.io.

Also, if this patch lands today, there's a good chance I won't be able to do much Rust coding over the long weekend in the US. So -1 to a globally breaking change right before a major US holiday.

@arcto
Copy link

arcto commented Nov 26, 2014

+1 for either @foo(...) or #foo(...). I slightly prefer the latter. It would be a good thing to get rid of the brackets.

@ftxqxd
Copy link
Contributor

ftxqxd commented Nov 26, 2014

What precisely is it that people see as an advantage in #[] or @ over the other? It would be nice to hear people’s opinions on each syntax, so we can know the perceived advantages and disadvantages of each syntax. Saying that this is just a ‘personal preference’ is true, but I think that to truly evaluate this RFC, we should discuss why one person’s preference should differ from another’s.

I personally consider @’s main advantages to be precedent (Python and Java use the same syntax for a general idea of attaching extra information to the following thing) and simplicity (only a single symbol). It has the disadvantage of being ambiguous in some cases. I like how the #[] syntax encapsulates it tightly into a single object with the square brackets, giving it a clear end point, and I also rather like the # character, but I don’t think that advantage outweighs the problem of simply being rather noisy due to the square brackets (and I haven’t seen any other language use such a unique syntax).

@glaebhoerl
Copy link
Contributor

Submitted #484 as an alternative (keep the existing syntax, just make the brackets optional).

@renato-zannon
Copy link

👎 I like #[foo] and #![foo] better, though I don't hate @/@!. What makes me -1 this is that it will break virtually every crate out there (again), and this time for an aesthetic change, with impromevements that are subjective at best :(

@bstrie
Copy link
Contributor

bstrie commented Nov 26, 2014

I don't think that breakage will be a big deal, given that we can ship a rudimentary tool to fix up code automatically. And this won't be the last time that Rust code will break, given the yet-forthcoming switch to unboxed closures.

I really don't care if the sigil is @ or #, but the brackets have to go.

@iirelu
Copy link

iirelu commented Nov 26, 2014

"It looks bad in my opinion" is not a good reason to introduce a major breaking change.

@wesleywiser
Copy link
Member

-1 I like the way attributes look currently. They remind me of attributes in F#:

[<EntryPoint>]
let main () = 
    printfn "Hello world"

@bstrie
Copy link
Contributor

bstrie commented Nov 26, 2014

@iirelu Familiarity for people coming from other languages is a good reason to introduce a major breaking change. Our current #[foo] syntax manages to be arbitrarily unfamiliar to anyone versed in C# attributes ([foo]), Java annotations (@foo), or C preprocessor directives (#foo). Given that attributes in Rust aren't really very special and are roughly analogous to Java annotations (and given that other elements of our syntax prevent us from doing exactly as C# does), I don't see why we wouldn't make the switch.

I should also point out that this change has been brewing since 2012 at least, though it was only made possible this year due the removal of the managed pointer syntax. This also would have been done last month had RFC #386 not decided to unfortunately entangle the change with a much more controversial attempt to unify the syntax of attributes and macros.

I'm sympathetic to the breakage argument, but not the extent of penalizing all future users and learners of the language in the years to come. See also how we ended up with Make's notorious whitespace syntax.

We can provide a tool to make the switch painless for library authors. We should provide such a tool. I would appreciate mention of this being added to the RFC.

@renato-zannon
Copy link

I guess I disagree with the familiarity argument, since I don't think the current syntax is all that different. But this might be my biases talking here, because I don't usually interact with Rust newbies.

I would feel much less strongly about the breakage point if something like @steveklabnik's approach on fail! -> panic! (submitting automatic pull requests) was done. I would be willing to help if it's deemed too time-consuming to implement.

@adamhjk
Copy link

adamhjk commented Nov 26, 2014

As an actual newcomer to the language, with background in perl, ruby, Erlang, clojure, JavaScript, and a smattering of c - there was nothing odd about the current syntax. I did have to understand what it was at all, but that would be true of the @ syntax as well. Honestly, # made sense to me because it was a comment in many other languages, and rust was using it as a 'special kind of comment'. I'm sure I would've adapted to the @ syntax just as well, but the mental mnemonic wouldn't have kicked in.

$0.02 from newb land.

@jminer
Copy link

jminer commented Nov 26, 2014

-1. I started learning Rust a few weeks ago, having used C#, C, C++, Java, Dart, and D before, and I've liked Rust's attribute syntax from the beginning. I've always thought that using @ for attributes is ugly, largely because the character is heavy and stands out so much. Using # for attributes is fitting because it is used in hashtags, another type of metadata. I don't see familiarity being a good reason to change, since C++ and C# don't use @ and hashtags use #.

@vadimcn
Copy link
Contributor

vadimcn commented Nov 26, 2014

-1 on #->@. As others have said above, for people with C/C++ background # associates with directives, and they are Rust's primary target audience. So the familiarity argument in the RFC is pretty dubious.
Please save @ for later (e.g. for a matrix multiplication operator).

@ftxqxd
Copy link
Contributor

ftxqxd commented Nov 27, 2014

@vadimcn We could use @ for both a binary operator and for the attribute syntax. As far as I can tell that’s not ambiguous, and we already use @ as a binary operator in patterns anyway. Also, using # for attributes can give the wrong idea; as I remarked above, I have seen people avoid using attributes because they looked too similar to C[++]’s preprocessor directives.

@emk
Copy link

emk commented Nov 28, 2014

OK, I've spent a while looking at Rust code using @test and #[test], and the new syntax is starting to grow on me, despite things like @!. So I withdraw my earlier semi-objections.

This change is still probably going to break the Rust web stacks for a couple of days, because the web dependency chain is so deep, and getting everybody to patch things and upload new crates will take a while.

@mangecoeur
Copy link

+1 @ is familiar, familiar is good for new people, and now is the time to make the change

@arthurprs
Copy link

-1 it takes just a few minutes to get familiar with the current syntax. No gain here.

@nrc
Copy link
Member

nrc commented Dec 3, 2014

We discussed this with the Rust team and although most of us like the look of @ vs #[...] we were put off by the parsing ambiguities and by so much churn so close to 1.0.

Thanks for writing the RFC!

@nrc nrc closed this Dec 3, 2014
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

Successfully merging this pull request may close these issues.