For User Defined Attributes.
In the north corner we have the current champeeeeon:
-------
[ ArgumentList ]
Pros:
precedent with C#
looks nice
Cons:
not so greppable
parsing ambiguity with [array literal].func();
------
In the south corner, there's the chaaaaallenger:
( ArgumentList )
Pros:
looks like existing attribute syntax
no parsing problems
Cons:
not as nice looking
------
No hitting below the belt! Let the games begin!

Actually, I find it even nicer looking than the other syntax.
Combine it with allowing the omission of the parens for a single
argument and allowing multiple specifications of it per
declaration, and it starts to look a whole lot like the built-in
attributes.
David

For User Defined Attributes.
In the north corner we have the current champeeeeon:
-------
[ ArgumentList ]
Pros:
precedent with C#
looks nice
Cons:
not so greppable
parsing ambiguity with [array literal].func();
------
In the south corner, there's the chaaaaallenger:
( ArgumentList )
Pros:
looks like existing attribute syntax
no parsing problems

Look like what is done in Java, python and PHP.

Cons:
not as nice looking
------
No hitting below the belt! Let the games begin!

BTW, I'm all for argument argument argument rather than (argumentlist)

For User Defined Attributes.
In the north corner we have the current champeeeeon:
-------
[ ArgumentList ]
Pros:
precedent with C#
looks nice
Cons:
not so greppable
parsing ambiguity with [array literal].func();
------
In the south corner, there's the chaaaaallenger:
( ArgumentList )
Pros:
looks like existing attribute syntax
no parsing problems
Cons:
not as nice looking
------
No hitting below the belt! Let the games begin!

For User Defined Attributes.
In the north corner we have the current champeeeeon:
-------
[ ArgumentList ]
Pros:
precedent with C#
looks nice
Cons:
not so greppable
parsing ambiguity with [array literal].func();
------
In the south corner, there's the chaaaaallenger:
( ArgumentList )
Pros:
looks like existing attribute syntax
no parsing problems
Cons:
not as nice looking
------
No hitting below the belt! Let the games begin!

I think ( ArgumentList ) would be more consistent with what D already
has, but my vot still goes for [ ArgumentList ] because personally I
find that 's make the code look "ugly". There are other languages where
the ' ' is only used for language features you shouldn't be using a lot.
Kind Regards
Benjamin Thaut

I actually quite liked Tristan's argument.
[attr, attr2] feels more like what it is, an annotation. It does nothing,
has no effect on the declaration on its own.
the attr syntax looks like existing attributes, and with that kinda comes
the presumption that they actually DO something, affect the code generated
in some way.
For that reason, I buy the argument that [attrs...] being visually distinct
makes more sense, more like what it is.
Perhaps it should be termed 'annotation' rather than 'attribute'?
On 6 November 2012 21:38, ponce <spam spam.org> wrote:

I like (ArgumentList) better for stated reason: it looks like
existing attributes.

I actually quite liked Tristan's argument.
[attr, attr2] feels more like what it is, an annotation. It does
nothing, has no effect on the declaration on its own.
the attr syntax looks like existing attributes, and with that kinda
comes the presumption that they actually DO something, affect the code
generated in some way.

This is definitively what they should do at some point.

For that reason, I buy the argument that [attrs...] being visually
distinct makes more sense, more like what it is.
Perhaps it should be termed 'annotation' rather than 'attribute'?
On 6 November 2012 21:38, ponce <spam spam.org <mailto:spam spam.org>>
wrote:
I like (ArgumentList) better for stated reason: it looks like
existing attributes.

I actually quite liked Tristan's argument.
[attr, attr2] feels more like what it is, an annotation. It
does nothing,
has no effect on the declaration on its own.
the attr syntax looks like existing attributes, and with that
kinda comes
the presumption that they actually DO something, affect the
code generated
in some way.
For that reason, I buy the argument that [attrs...] being
visually distinct
makes more sense, more like what it is.
Perhaps it should be termed 'annotation' rather than
'attribute'?
On 6 November 2012 21:38, ponce <spam spam.org> wrote:

I like (ArgumentList) better for stated reason: it looks like
existing attributes.

For User Defined Attributes.
In the north corner we have the current champeeeeon:
-------
[ ArgumentList ]
Pros:
precedent with C#
looks nice
Cons:
not so greppable
parsing ambiguity with [array literal].func();
------
In the south corner, there's the chaaaaallenger:
( ArgumentList )
Pros:
looks like existing attribute syntax
no parsing problems
Cons:
not as nice looking
------
No hitting below the belt! Let the games begin!

For User Defined Attributes.
In the north corner we have the current champeeeeon:
-------
[ ArgumentList ]
Pros:
precedent with C#
looks nice
Cons:
not so greppable
parsing ambiguity with [array literal].func();
------
In the south corner, there's the chaaaaallenger:
( ArgumentList )
Pros:
looks like existing attribute syntax
no parsing problems
Cons:
not as nice looking
------
No hitting below the belt! Let the games begin!

I vote for ( ArgumentList ). If this is syntax chosen I also hope
attribute will be legal as well.
--
/Jacob Carlborg

I'd like to re-enforce the consideration that attribute() makes it looks
like they affect the code generation somehow... they're really just
annotations.
On 6 November 2012 21:47, Jacob Carlborg <doob me.com> wrote:

On 2012-11-06 20:18, Walter Bright wrote:

For User Defined Attributes.
In the north corner we have the current champeeeeon:
-------
[ ArgumentList ]
Pros:
precedent with C#
looks nice
Cons:
not so greppable
parsing ambiguity with [array literal].func();
------
In the south corner, there's the chaaaaallenger:
( ArgumentList )
Pros:
looks like existing attribute syntax
no parsing problems
Cons:
not as nice looking
------
No hitting below the belt! Let the games begin!

I vote for ( ArgumentList ). If this is syntax chosen I also hope
attribute will be legal as well.
--
/Jacob Carlborg

I'd like to re-enforce the consideration that attribute()
makes it
looks like they affect the code generation somehow... they're
really
just annotations.

I still like the syntax.

I'd also like to add that the OP argument is false.
Sure, the attributes themselves are just meta-data and you can
use them for purely informative purposes (to annotate with
documentation, author names, versions, license, etc..) but more
commonly attributes are intended to be introspected on at CT or
RT and used to *indirectly cause some processing*.
The end result is the same and user defined attributes should be
consistent with built-in ones.
Syntax wise, I agree the C# version is /slightly/ more pleasant
to the eye than the Java one but given the possible grammar
ambiguities and the consistency with buit-ins, (attributes) win
by a landslide.

I'd like to re-enforce the consideration that attribute()
makes it looks
like they affect the code generation somehow... they're really
just
annotations.

Why would look like that to you? Actually, seems to yell
¬Ľannotation¬ę to me, probably because of my (limited) exposure
to Python.
And don't forget that UDAs _do_ in practice have an effect on
code generation, at least a lot more than safe-ty attributes.
Whether the mechanism by which they gain that effect is built
into the compiler or implemented in a library doesn't matter to
the user of a library.
David

I'd like to re-enforce the consideration that attribute() makes it
looks like they affect the code generation somehow... they're really
just annotations.
On 6 November 2012 21:47, Jacob Carlborg <doob me.com
<mailto:doob me.com>> wrote:
On 2012-11-06 20:18, Walter Bright wrote:
For User Defined Attributes.
In the north corner we have the current champeeeeon:
-------
[ ArgumentList ]
Pros:
precedent with C#
looks nice
Cons:
not so greppable
parsing ambiguity with [array literal].func();
------
In the south corner, there's the chaaaaallenger:
( ArgumentList )
Pros:
looks like existing attribute syntax
no parsing problems
Cons:
not as nice looking
------
No hitting below the belt! Let the games begin!
I vote for ( ArgumentList ). If this is syntax chosen I also hope
attribute will be legal as well.
--
/Jacob Carlborg

Speaking from C# point of view, the same argument can be used, because
in .NET [] attributes might change the way the code gets generated.
Some of them like are even reckognized by the JIT/NGEN.
--
Paulo

For User Defined Attributes.
In the north corner we have the current champeeeeon:
-------
[ ArgumentList ]
Pros:
precedent with C#
looks nice
Cons:
not so greppable
parsing ambiguity with [array literal].func();
------
In the south corner, there's the chaaaaallenger:
( ArgumentList )
Pros:
looks like existing attribute syntax
no parsing problems
Cons:
not as nice looking
------
No hitting below the belt! Let the games begin!

At first I liked the C# style, but it just does not mix well
with D's system attributes. So my vote is for..
( ArgumentList )
I would prefer if I could enclose system and user attributes in
the parenthesis, with no idea how that would work though.

For User Defined Attributes.
In the north corner we have the current champeeeeon:
-------
[ ArgumentList ]
Pros:
precedent with C#
looks nice
Cons:
not so greppable
parsing ambiguity with [array literal].func();
------
In the south corner, there's the chaaaaallenger:
( ArgumentList )
Pros:
looks like existing attribute syntax
no parsing problems
Cons:
not as nice looking
------
No hitting below the belt! Let the games begin!

For User Defined Attributes.
In the north corner we have the current champeeeeon:
-------
[ ArgumentList ]
Pros:
precedent with C#
looks nice
Cons:
not so greppable
parsing ambiguity with [array literal].func();
------
In the south corner, there's the chaaaaallenger:
( ArgumentList )
Pros:
looks like existing attribute syntax
no parsing problems
Cons:
not as nice looking
------
No hitting below the belt! Let the games begin!

For User Defined Attributes.
In the north corner we have the current champeeeeon:
-------
[ ArgumentList ]
Pros:
precedent with C#
looks nice
Cons:
not so greppable
parsing ambiguity with [array literal].func();
------
In the south corner, there's the chaaaaallenger:
( ArgumentList )
Pros:
looks like existing attribute syntax
no parsing problems
Cons:
not as nice looking
------
No hitting below the belt! Let the games begin!

With [] I expect array operations; can I slice it?

this is a really good point. they are a tuple, you can slice it, iterate
it...
further supports [] to my mind ;)

For User Defined Attributes.
In the north corner we have the current champeeeeon:
-------
[ ArgumentList ]
Pros:
precedent with C#
looks nice
Cons:
not so greppable
parsing ambiguity with [array literal].func();
------
In the south corner, there's the chaaaaallenger:
( ArgumentList )
Pros:
looks like existing attribute syntax
no parsing problems
Cons:
not as nice looking
------
No hitting below the belt! Let the games begin!

For User Defined Attributes.
In the north corner we have the current champeeeeon:
-------
[ ArgumentList ]
Pros:
precedent with C#
looks nice
Cons:
not so greppable
parsing ambiguity with [array literal].func();
------
In the south corner, there's the chaaaaallenger:
( ArgumentList )
Pros:
looks like existing attribute syntax
no parsing problems
Cons:
not as nice looking
------
No hitting below the belt! Let the games begin!

One more vote for ( ArgumentList ) with optional () for simple ones -
they seem like they would fit with the rest of the language much more nicely

For User Defined Attributes.
In the north corner we have the current champeeeeon:
-------
[ ArgumentList ]
Pros:
precedent with C#
looks nice
Cons:
not so greppable
parsing ambiguity with [array literal].func();
------
In the south corner, there's the chaaaaallenger:
( ArgumentList )
Pros:
looks like existing attribute syntax
no parsing problems
Cons:
not as nice looking
------
No hitting below the belt! Let the games begin!

I vote for (ArgumentList).
Or Arg1 Arg2 ... as somebody mentioned.
It's more consistent with existing -syntax. Reusing [] is bad because
it visually conflicts with array literals (and makes parsing harder to
boot). is a unique symbol that, so far, is associated with attributes,
so it makes sense to use it also to mark user-defined attributes.
I don't buy the argument that other languages have a different syntax.
We're talking about D here, and what is chosen should make sense in the
context of D, without undue influence from other languages.
T
--
If the comments and the code disagree, it's likely that *both* are wrong. --
Christopher

I agree with David and deadalnix agument wise, so:
(attriblist) or attrib1 attrib2
with the hope that this syntax is extensible enough to make it possible
to implement something like safe or noheap as library functionality at
some day.

Definitely (ArgumentList). It fits with what other languages do, and it
matches
what we're already doing for attributes. I also think that's what pretty much
everyone was figuring would be used for user-defined attributes. The only major
problem would be if ArgumentList is allowed when there's only a single
argument, then code could break when new built-in attributes are added.
- Jonathan M Davis

Definitely (ArgumentList). It fits with what other languages do, and it
matches
what we're already doing for attributes. I also think that's what pretty much
everyone was figuring would be used for user-defined attributes. The only major
problem would be if ArgumentList is allowed when there's only a single
argument, then code could break when new built-in attributes are added.

Definitely (ArgumentList). It fits with what other languages do, and it
matches
what we're already doing for attributes. I also think that's what pretty much
everyone was figuring would be used for user-defined attributes. The only major
problem would be if ArgumentList is allowed when there's only a single
argument, then code could break when new built-in attributes are added.

Can you explain that code breakage ?

C++11 has had problems adding new keywords, as about every identifier somewhere
has been used by someone's C++ source code, and they don't want to break
existing code. So C++11 winds up with awful things like "decltype".

Definitely (ArgumentList). It fits with what other languages do, and
it matches
what we're already doing for attributes. I also think that's what
pretty much
everyone was figuring would be used for user-defined attributes. The
only major
problem would be if ArgumentList is allowed when there's only a single
argument, then code could break when new built-in attributes are added.

Can you explain that code breakage ?

C++11 has had problems adding new keywords, as about every identifier
somewhere has been used by someone's C++ source code, and they don't
want to break existing code. So C++11 winds up with awful things like
"decltype".

OK I understand. This is fixable easily by adding thoses magic attribute
in object and using regular lookup rules.

Definitely (ArgumentList). It fits with what other languages do, and
it matches
what we're already doing for attributes. I also think that's what
pretty much
everyone was figuring would be used for user-defined attributes. The
only major
problem would be if ArgumentList is allowed when there's only a single
argument, then code could break when new built-in attributes are added.

Can you explain that code breakage ?

C++11 has had problems adding new keywords, as about every identifier
somewhere has been used by someone's C++ source code, and they don't
want to break existing code. So C++11 winds up with awful things like
"decltype".

OK I understand. This is fixable easily by adding thoses magic attribute
in object and using regular lookup rules.

It would still break code, because then there would be a conflict which would
have to be resolved. It's the same as if we were to do something like add a
function to std.file called find. Anything importing both std.algorithm and
std.file would break (assuming that the arguments matched both).
To some extent, this is unavoidable. Adding _any_ function to a library risks
breaking user code if there's any other function that it uses which has the
same name and similar enough arguments. That's what we get for automatically
inferring which function and requiring the full path for disambiguation rather
than requiring the full path unless a specific command makes it so that it's
unnecessary (e.g. aliasing std.algorithm.find to find).
So, if we want to avoid breaking code when adding new built-in attributes,
we're going to have to define custom attributes in a way which they can't ever
conflict with built-in ones - which would probably mean making customAttribute
illegal and require (customAttribute). But if we're willing to break user
code when adding a new attribute, forcing user code to change its attribute
names or give their full path, then we can allow customAttribute.
- Jonathan M Davis

Definitely (ArgumentList). It fits with what other languages do, and
it matches
what we're already doing for attributes. I also think that's what
pretty much
everyone was figuring would be used for user-defined attributes. The
only major
problem would be if ArgumentList is allowed when there's only a single
argument, then code could break when new built-in attributes are added.

Can you explain that code breakage ?

C++11 has had problems adding new keywords, as about every identifier
somewhere has been used by someone's C++ source code, and they don't
want to break existing code. So C++11 winds up with awful things like
"decltype".

OK I understand. This is fixable easily by adding thoses magic attribute
in object and using regular lookup rules.

It would still break code, because then there would be a conflict which would
have to be resolved. It's the same as if we were to do something like add a
function to std.file called find. Anything importing both std.algorithm and
std.file would break (assuming that the arguments matched both).
To some extent, this is unavoidable. Adding _any_ function to a library risks
breaking user code if there's any other function that it uses which has the
same name and similar enough arguments. That's what we get for automatically
inferring which function and requiring the full path for disambiguation rather
than requiring the full path unless a specific command makes it so that it's
unnecessary (e.g. aliasing std.algorithm.find to find).
So, if we want to avoid breaking code when adding new built-in attributes,
we're going to have to define custom attributes in a way which they can't ever
conflict with built-in ones - which would probably mean making customAttribute
illegal and require (customAttribute). But if we're willing to break user
code when adding a new attribute, forcing user code to change its attribute
names or give their full path, then we can allow customAttribute.
- Jonathan M Davis

As you stated, this is true for ANY identifier, so I don't see why this
pop in this particular discussion.

As you stated, this is true for ANY identifier, so I don't see why this
pop in this particular discussion.

Because it sucks, and being able to avoid having that problem spread is a good
thing. Just because something is a problem in one place doesn't mean that it's
okay to have that same problem somewhere else.
- Jonathan M Davis

It would still break code, because then there would be a conflict which
would have to be resolved.

I really doubt we're going to create any new language properties
(you're the only one I can see suggesting this). And if we are, we
should use special identifiers that begin with underscores. In any
case, we can always use an alias to resolve conflicts.

It would still break code, because then there would be a conflict which
would have to be resolved.

I really doubt we're going to create any new language properties
(you're the only one I can see suggesting this). And if we are, we
should use special identifiers that begin with underscores. In any
case, we can always use an alias to resolve conflicts.

Actually, let me give you a better argument.
Let's say you implement your own (NoGC) attribute that you use in
your own library. You use it like so:
(NoGC) class Foo { }
And somewhere down the road 5 months from now druntime introduces it's
own NoGC attribute. Personally I would rather have a compile-time
error due to clashing symbol names right then and there. Otherwise I
could easily end up in a situation where I **forget** to parenthesize
my custom NoGC attribute and end up using the druntime one:
(NoGC) class Foo { }
NoGC class Bar { } // oops, I meant (NoGC)
I really don't think we should have parenthesis dictate name lookup,
it's way too easy to screw things up like that. Let the symbols clash
so I can fix the problem with the already existing alias tools in D:
alias mymod.NoGC MyNoGC;
(MyNoGC) class Foo { }
MyNoGC class Bar { }
or simply:
(mymod.NoGC) class Foo { }
mymod.NoGC class Bar { }
Then I can be at ease knowing I'm not accidentally using one attribute
or the other because of an issue with missing parens.

C++11 has had problems adding new keywords, as about every identifier
somewhere has been used by someone's C++ source code, and they don't
want to break existing code. So C++11 winds up with awful things like
"decltype".

Just create a new attribute, call it "builtin" or something similar,
which takes attributes as arguments, i.e.
builtin(shared) int a;
builtin(property) int b;
I'm not suggesting that we should change the existing shared and
property, I just used them as an example.
--
/Jacob Carlborg

C++11 has had problems adding new keywords, as about every
identifier
somewhere has been used by someone's C++ source code, and they
don't
want to break existing code. So C++11 winds up with awful
things like
"decltype".

Just create a new attribute, call it "builtin" or something
similar, which takes attributes as arguments, i.e.
builtin(shared) int a;
builtin(property) int b;
I'm not suggesting that we should change the existing shared
and property, I just used them as an example.

I honestly don't get why we keep reinventing the concept of
namespaces.
I agree with Jonathan regarding the identifier look-up rules in D.
"std.algorithm.find" really should be *the default* unless the
user specifically aliases that to "find" whereas now we have the
exact opposite. But even without this we still should use D's
already existing namespace solution - *the module system*. We
should take a lesson from other platforms such as Java and .NET
where everything is neatly organized. Let's stop this global
identifiers nightmare!
On that note, here's some things we *should not do*:
- put unrelated random stuff in object.d
- add more redundant ways to define namespaces such as
__identifier, builtin(identifier), attribute(identifier),
identifier, etc, etc..
- add more keywords because they conflict with global
identifiers.
- have _huge_ single modules in Phobos that contain everything
and ythe kitchen sink. I still hate with passion the
"std.algorithm" "module". It's like opening a shop called "A
Shop" or naming a newspaper "Newspaper".
Proper organization is not inherently evil and we should not
complicate the language design to compensate our current
sloppiness.

Definitely (ArgumentList). It fits with what other languages do, and it
matches
what we're already doing for attributes. I also think that's what pretty much
everyone was figuring would be used for user-defined attributes. The only
major
problem would be if ArgumentList is allowed when there's only a single
argument, then code could break when new built-in attributes are added.

Easy - do not introduce any new *global* built-in attributes, ever. There's no
reason why they all can't use the same look-up rules.
As to the syntax - it doesn't matter, as long as it isn't "[ArgumentList]" as
that
one is ambiguous (from a programmer POV, even if the compiler could deal with
it -
which i'm not convinced is the case here, considering all contexts where
attributes have to be allowed and the inevitable evolution of this feature).
" [ArgumentList]".
artur

vote++
It has all the benefits of ' (...)' (which are very compelling on
their own), but also has the *ONE* benefit of '[...]': Much less
getting lost in stupid parenthesis, as demonstrated here:
http://forum.dlang.org/thread/k7afq6$2832$1 digitalmars.com?page=14#post-puseurlcwbgvigwkdowu:40forum.dlang.org

vote++
It has all the benefits of ' (...)' (which are very compelling on
their own), but also has the *ONE* benefit of '[...]': Much less
getting lost in stupid parenthesis, as demonstrated here:
http://forum.dlang.org/thread/k7afq6$2832$1 digitalmars.com?page=14#post-puseurlcwbgvigwkdowu:40forum.dlang.org

I hadn't replied to this thread earlier because I didn't have a strong
opinion either way, but, this suggestion appears to be the best of both
worlds. So..
vote++
R
--
Using Opera's revolutionary email client: http://www.opera.com/mail/

vote++
It has all the benefits of ' (...)' (which are very compelling on
their own), but also has the *ONE* benefit of '[...]': Much less
getting lost in stupid parenthesis, as demonstrated here:
http://forum.dlang.org/thread/k7afq6$2832$1 digitalmars.com?page=14#post-puseurlcwbgvigwkdowu:40forum.dlang.org

I hadn't replied to this thread earlier because I didn't have a strong
opinion either way, but, this suggestion appears to be the best of both
worlds. So..
vote++

vote++
It has all the benefits of ' (...)' (which are very compelling on
their own), but also has the *ONE* benefit of '[...]': Much less
getting lost in stupid parenthesis, as demonstrated here:
http://forum.dlang.org/thread/k7afq6$2832$1 digitalmars.com?page=14#post-puseurlcwbgvigwkdowu:40forum.dlang.org

This is how that example would look like with my syntax:
http://pastebin.com/8Ve5KS49
I think it looks better in most cases
--
/Jacob Carlborg

vote++
It has all the benefits of ' (...)' (which are very compelling on
their own), but also has the *ONE* benefit of '[...]': Much less
getting lost in stupid parenthesis, as demonstrated here:
http://forum.dlang.org/thread/k7afq6$2832$1 digitalmars.com?page=14#post-puseurlcwbgvigwkdowu:40forum.dlang.org

vote++
It has all the benefits of ' (...)' (which are very compelling on
their own), but also has the *ONE* benefit of '[...]': Much less
getting lost in stupid parenthesis, as demonstrated here:
http://forum.dlang.org/thread/k7afq6$2832$1 digitalmars.com?page=14#post-puseurlcwbgvigwkdowu:40forum.dlang.org

[...]
Hmm. Having seen both () and [] in actual sample code, I have to say
that () is visually less distracting and more pleasant to read (to me,
anyway, YMMV). I don't like [] because it just stands out too much.
T
--
"I'm running Windows '98." "Yes." "My computer isn't working now." "Yes, you
already said that." -- User-Friendly

I like Jacobs proposal more. On many keyboards are [ and ]
notoriously hard to type . Despite that: please make any form of
brackets optional. I wouldn't consider any possibly breaking
changes in the future for two reasons:
First: New buildin UDA can go into modules and adhere to normal
scoping rules.
Second: When the time comes, we'll hopefully have enough
reengineering tools that can fully qualify any conflicting uses
of a name automatically.

vote++
It has all the benefits of ' (...)' (which are very compelling on
their own), but also has the *ONE* benefit of '[...]': Much less
getting lost in stupid parenthesis, as demonstrated here:
http://forum.dlang.org/thread/k7afq6$2832$1 digitalmars.com?page=14#post-puseurlcwbgvigwkdowu:40forum.dlang.org

Definitely (ArgumentList). It fits with what other languages do, and it
matches what we're already doing for attributes. I also think that's what
pretty much everyone was figuring would be used for user-defined
attributes. The only major problem would be if ArgumentList is allowed
when there's only a single argument, then code could break when new
built-in attributes are added.

Easy - do not introduce any new *global* built-in attributes, ever. There's
no reason why they all can't use the same look-up rules.

That's not really acceptable IMHO. Not being able to add new attributes to the
language itself in the future is way too restrictive, and I expect that we'll
come up with more that we want to add eventually. Designing custom attributes
in a way that is guaranteed to conflict with that is a bad idea. We're
restricting ourselves and causing problems for ourselves later when we could
easily avoid doing so.
- Jonathan M Davis

Definitely (ArgumentList). It fits with what other languages do, and it
matches what we're already doing for attributes. I also think that's what
pretty much everyone was figuring would be used for user-defined
attributes. The only major problem would be if ArgumentList is allowed
when there's only a single argument, then code could break when new
built-in attributes are added.

Easy - do not introduce any new *global* built-in attributes, ever. There's
no reason why they all can't use the same look-up rules.

That's not really acceptable IMHO. Not being able to add new attributes to the
language itself in the future is way too restrictive, and I expect that we'll
come up with more that we want to add eventually. Designing custom attributes
in a way that is guaranteed to conflict with that is a bad idea. We're
restricting ourselves and causing problems for ourselves later when we could
easily avoid doing so.
- Jonathan M Davis

Language attribute can be added in object.d and regular lookup rule apply.

Designing custom attributes
in a way that is guaranteed to conflict with that is a bad idea.

Well, the same could be said about language keywords as well, or
really just adding names in general. I don't see a good reason
why special contortions for user defined annotations should be
required, if simply adding a name to Phobos (even a private one!)
can have just the same effect.
David

Actually, let me give you a better argument.
Let's say you implement your own (NoGC) attribute that you use in
your own library. You use it like so:
(NoGC) class Foo { }
And somewhere down the road 5 months from now druntime introduces it's
own NoGC attribute. Personally I would rather have a compile-time
error due to clashing symbol names right then and there. Otherwise I
could easily end up in a situation where I **forget** to parenthesize
my custom NoGC attribute and end up using the druntime one:

Definitely (ArgumentList). It fits with what other languages do, and it
matches what we're already doing for attributes. I also think that's what
pretty much everyone was figuring would be used for user-defined
attributes. The only major problem would be if ArgumentList is allowed
when there's only a single argument, then code could break when new
built-in attributes are added.

Easy - do not introduce any new *global* built-in attributes, ever. There's
no reason why they all can't use the same look-up rules.

That's not really acceptable IMHO. Not being able to add new attributes to the
language itself in the future is way too restrictive, and I expect that we'll
come up with more that we want to add eventually. Designing custom attributes
in a way that is guaranteed to conflict with that is a bad idea. We're
restricting ourselves and causing problems for ourselves later when we could
easily avoid doing so.

What I'm saying is that any new "built-in" attributes (and there *will* be many
of these) can have their own namespace. Yeah, it could make the code a little
more verbose, but it makes several problems go away.
Eg
import attr = core.attr; // Could be implicit, ie in object.d.
int f() [attr.pure, attr.deprecated("Use something else"), attr.inline]
{return 42;}
I said attr.pure, but migrating the existing built-ins is not worth the cost,
at least not until other language changes happen.
The above is too verbose? Then
int f() attr[pure, deprecated("Use something else"), inline] {return 42;}
is possible (which works just as the above - looks for the named attributes
in the "attr" scope).
Almost as terse as the current approach, but more powerful. And not as bad as
context sensitive keywords (which would be another way to reduce collisions
with other user-defined identifiers w/o resorting to pragmas, strings, etc).
artur

I think that [] is sufficiently distinct from built-in
attributes, unlike (), but sadly, there's no nice way to parse
it at statement scope. There are in fact a couple of ambiguous
cases in the parser already; let's not introduce any more, lest
we lose the ability to call D easy to parse.
(foo) looks too similar to built-in attributes. And let's face
it; these annotations are actually quite different (I too prefer
the more accurate name, 'annotations') from built-in attributes,
the former cannot replace the latter any time soon.
I want to hear what people think about [] at declaration scope
and [] at statement scope. Too complicated to remember?

ArgumentList makes me think I'm on Twitter. #joke
Personally, I also like <ArgumentList>. Prior to property and
family being introduced, I'd have gone with [ArgumentList]. But
since is the prefix for attributes in D, let's stick with it
for UDAs.
And as to any clashes between UDAs and possible future built-in
ones, I'd say the language has first dibs on names and it's up to
people writing UDAs to avoid using names that sound like language
constructs.

I think that's the first time I've heard someone suggest something be
borrowed from VB. :p

Of course we all take it for granted that Basic sux and does everything wrong,
and this has been going on for 30+ years. But in one of the early design
sessions on D, I'd ask "Since Basic sux, why is its string handling so nice &
convenient, and C's string handling is such a misery?"
So Basic did provide some motivation.

For User Defined Attributes.
In the north corner we have the current champeeeeon:
-------
[ ArgumentList ]
Pros:
precedent with C#
looks nice
Cons:
not so greppable
parsing ambiguity with [array literal].func();
------
In the south corner, there's the chaaaaallenger:
( ArgumentList )
Pros:
looks like existing attribute syntax
no parsing problems
Cons:
not as nice looking
------
No hitting below the belt! Let the games begin!

[], because should be reserved for future language keywords.
Whenever people post suggested language features that require some
marking, they introduce a new attribute, because introducing a plain
keyword breaks code. If you have UDAs, this further limits language
expansion.
Example: let's say you want to introduce a "nogc" mark:
1. Not a nogc keyword, that could break "bool nogc;"
2. If you have , nogc could break an "enum nogc;" attribute.
3. Now you're stuck with __nogc or #nogc or something uglier.
There is a familiar-to-other-langauges advantage to , but there is a
better-than-other-languages advantage to [].
My thoughts,
NMS

For User Defined Attributes.
In the north corner we have the current champeeeeon:
-------
[ ArgumentList ]
Pros:
precedent with C#
looks nice
Cons:
not so greppable
parsing ambiguity with [array literal].func();
------
In the south corner, there's the chaaaaallenger:
( ArgumentList )
Pros:
looks like existing attribute syntax
no parsing problems
Cons:
not as nice looking
------
No hitting below the belt! Let the games begin!

[], because should be reserved for future language keywords.
Whenever people post suggested language features that require some
marking, they introduce a new attribute, because introducing a plain
keyword breaks code. If you have UDAs, this further limits language
expansion.
Example: let's say you want to introduce a "nogc" mark:
1. Not a nogc keyword, that could break "bool nogc;"
2. If you have , nogc could break an "enum nogc;" attribute.
3. Now you're stuck with __nogc or #nogc or something uglier.
There is a familiar-to-other-langauges advantage to , but there is a
better-than-other-languages advantage to [].
My thoughts,
NMS

I think D has already too many feature, and that many of them can be
implemented as attribute + AST processing.
D should work toward getting this AST stuff and stop adding new keywords
all the time.

I think D has already too many feature, and that many of them can be
implemented as attribute + AST processing.
D should work toward getting this AST stuff and stop adding new keywords
all the time.

I completely agree.

Which features are that? It would likely require a major
rewrite of many routines. Who would want to go through all
that and the following wave of bugs - some of which may have
already occurred in the past.
foreach and scope(...) lowerings are essentially AST
operations. Are there other D features you would implement as
AST processing, maybe a link to an earlier post ?
How close is Rust currently to offering flexible AST
manipulation for lowerings/attributes/macros, does anyone
know ?
--
Marco

Which features are that? It would likely require a major
rewrite of many routines. Who would want to go through all
that and the following wave of bugs - some of which may have
already occurred in the past.
foreach and scope(...) lowerings are essentially AST
operations. Are there other D features you would implement as
AST processing, maybe a link to an earlier post ?

"synchronized" is another that I think would be easy to do with AST
macros. Perhaps "with". It's probably not worth replacing existing
language features with macros just for the sake of it. But for future
features AST macros could perhaps be used instead.

How close is Rust currently to offering flexible AST
manipulation for lowerings/attributes/macros, does anyone
know ?

I have no idea. I haven't looked at Rust in this area.
--
/Jacob Carlborg

[], because should be reserved for future language keywords.
Whenever people post suggested language features that require some
marking, they introduce a new attribute, because introducing a plain
keyword breaks code. If you have UDAs, this further limits language
expansion.
Example: let's say you want to introduce a "nogc" mark:
1. Not a nogc keyword, that could break "bool nogc;"
2. If you have , nogc could break an "enum nogc;" attribute.
3. Now you're stuck with __nogc or #nogc or something uglier.
There is a familiar-to-other-langauges advantage to , but there is a
better-than-other-languages advantage to [].
My thoughts,
NMS

I think D has already too many feature, and that many of them can be
implemented as attribute + AST processing.

+1

D should work toward getting this AST stuff and stop adding new keywords
all the time.

I think D has already too many feature, and that many of them can be
implemented as attribute + AST processing.

=20
+1
=20

Doesn't that still amount to the same amount of features though? At
least from the user's standpoint anyway. Plus, I would imagine
that library-implemented features would be slower to compile (simply
because it's just that much more to be compiled).
Not that I'm necessarily saying "Always stuff everything into the
language forever!" I just don't see it as quite so clear-cut.

[...]Plus, I would imagine
that library-implemented features would be slower to compile (simply
because it's just that much more to be compiled).

Also, these particular sorts of things (compile time processing of
things that are in-library) essentially amount to executing interpreted
code to compile. Sure, that's very powerful, and very well worth having,
but should it really be done for very common features? For common
features, I'd imagine native non-"interpreted" support would help
compilation speed, which is one of D's major goals and benefits.
Suddenly interpreting large parts of the language might work against
that.

Not that I'm necessarily saying "Always stuff everything into the
language forever!" I just don't see it as quite so clear-cut.

[...]Plus, I would imagine
that library-implemented features would be slower to compile (simply
because it's just that much more to be compiled).

Also, these particular sorts of things (compile time processing of
things that are in-library) essentially amount to executing interpreted
code to compile. Sure, that's very powerful, and very well worth having,
but should it really be done for very common features? For common
features, I'd imagine native non-"interpreted" support would help
compilation speed, which is one of D's major goals and benefits.
Suddenly interpreting large parts of the language might work against
that.

If we finally get to the usual byte-code interpreter then it is more the
sufficiently fast to do trivial re-writes that features like
synchronized are all about.
Anyway I'm not for trying to redo all (if any) of the built-in stuff. If
it's bug free and works, fine let it be. We can't remove it anyway. I
just anticipate a couple more features to crop up if UDA dropping from
nowhere is any indicator. And then another tiny most useful thing, and
another one, and ...

Not that I'm necessarily saying "Always stuff everything into the
language forever!" I just don't see it as quite so clear-cut.

I think D has already too many feature, and that many of them can be
implemented as attribute + AST processing.

+1

Doesn't that still amount to the same amount of features though? At
least from the user's standpoint anyway. Plus, I would imagine
that library-implemented features would be slower to compile (simply
because it's just that much more to be compiled).
Not that I'm necessarily saying "Always stuff everything into the
language forever!" I just don't see it as quite so clear-cut.

It have several advantages.
It is easy to test a feature as a lib, and then include it later in the
standard lib if it does make sense. This is a great improvement as it
don't require hacking the compiler.
This allow many people to play around with the feature they like without
breaking the language in many pieces. As before, successful features can
be included.
Implementing a feature don't require anymore to know the compiler
internal, and do not require either to know other feature internals.
A new feature in compiler A is available in other compiler as well at
the same time. Same goes for tooling around the language. Now, it is
almost impossible to provide proper tooling around D because new feature
are dropped into dmd master quite often and all tools have to be updated
(most people give up at some point).
As of speed, some people, including me but I'm not the only one, are
working toward JIT compile for CTFE. With some bytecode caching, I'm
pretty sure really good performance can be achieved (unless the
feature's implementation suck badly).

My vote goes to (a,b,c) and a b c.
I never understood why some builtin storage class keywords have
in front of them (e.g. property, safe, disable) and some don't
(e.g. pure, nothrow).
IMHO the cleanest design would be to have builtins as plain
keywords (ie. no in front). And then xxx is reserved for UDA.
I understand that this would be a breaking change and not likely
to happen - just want to know the reasoning behind it.
/Jonas

My vote goes to (a,b,c) and a b c.
I never understood why some builtin storage class keywords have
in front of them (e.g. property, safe, disable) and some don't
(e.g. pure, nothrow).
IMHO the cleanest design would be to have builtins as plain
keywords (ie. no in front). And then xxx is reserved for UDA.
I understand that this would be a breaking change and not likely
to happen - just want to know the reasoning behind it.

It mainly came down to not wanting to add new keywords. By using safe instead
of safe, safe could still be used as a variable or function or whatnot. There
was some discussion of which should have on them on which not (e.g. nothrow
vs nothrow was debated), but the decision was fairly arbitrary. If anything
though, had we not cared about breaking code or whether D looked similar to
other languages, we probably would have made _all_ attributes start with
(including stuff like public). It would have been wonderfully consistent that
way, but it wasn't ultimately deemed a good idea.
So, basically, was introduced to avoid adding more keywords. It certainly
makes sense to extend it for using with user defined attributes, but that
wasn't really the original intention.
- Jonathan M Davis

It mainly came down to not wanting to add new keywords. By using safe instead
of safe, safe could still be used as a variable or function or whatnot. There
was some discussion of which should have on them on which not (e.g. nothrow
vs nothrow was debated), but the decision was fairly arbitrary. If anything
though, had we not cared about breaking code or whether D looked similar to
other languages, we probably would have made _all_ attributes start with
(including stuff like public). It would have been wonderfully consistent that
way, but it wasn't ultimately deemed a good idea.

My vote goes to (a,b,c) and a b c.
I never understood why some builtin storage class keywords
have
in front of them (e.g. property, safe, disable) and some
don't
(e.g. pure, nothrow).
IMHO the cleanest design would be to have builtins as plain
keywords (ie. no in front). And then xxx is reserved for
UDA.
I understand that this would be a breaking change and not
likely
to happen - just want to know the reasoning behind it.

It mainly came down to not wanting to add new keywords. By
using safe instead
of safe, safe could still be used as a variable or function or
whatnot. There
was some discussion of which should have on them on which not
(e.g. nothrow
vs nothrow was debated), but the decision was fairly
arbitrary. If anything
though, had we not cared about breaking code or whether D
looked similar to
other languages, we probably would have made _all_ attributes
start with
(including stuff like public). It would have been wonderfully
consistent that
way, but it wasn't ultimately deemed a good idea.
So, basically, was introduced to avoid adding more keywords.
It certainly
makes sense to extend it for using with user defined
attributes, but that
wasn't really the original intention.
- Jonathan M Davis

I we were to allow for foobar style UDA then "safe" would have
to be a reserved keyword somehow. Otherwise I do not know what
this would mean:
struct safe { }
safe void foobar() { }
/Jonas

I we were to allow for foobar style UDA then "safe" would have to be
a reserved
keyword somehow. Otherwise I do not know what this would mean:
struct safe { }
safe void foobar() { }

Yes, I agree this is a significant problem.

I think it's solvable. The basic approach would be to plop types "safe",
"nothrow" etc. in object.di and then let them just behave like all other
arguments.

Consider that if we do that, then someone will need to disambiguate with:
object.safe
which is ambiguous:
a.b .c x = 3;
or is it:
a .b.c x = 3;
?
Another problem is it pushes off recognition of safe from the parser to the
semantic analyzer. This has unknown forward reference complications.

I we were to allow for foobar style UDA then "safe" would have to be
a reserved
keyword somehow. Otherwise I do not know what this would mean:
struct safe { }
safe void foobar() { }

Yes, I agree this is a significant problem.

I think it's solvable. The basic approach would be to plop types "safe",
"nothrow" etc. in object.di and then let them just behave like all
other arguments.

Consider that if we do that, then someone will need to disambiguate with:
object.safe
which is ambiguous:
a.b .c x = 3;
or is it:
a .b.c x = 3;
?
Another problem is it pushes off recognition of safe from the parser to
the semantic analyzer. This has unknown forward reference complications.

In that case $(object.safe) would be required - the shortcut then only
works for simple identifiers and would error out going with the second
option ("object is not an attribute" or something).
Templates basically have the same ambiguity: A!x.y.z

I we were to allow for foobar style UDA then "safe" would have to be
a reserved
keyword somehow. Otherwise I do not know what this would mean:
struct safe { }
safe void foobar() { }

Yes, I agree this is a significant problem.

I think it's solvable. The basic approach would be to plop types "safe",
"nothrow" etc. in object.di and then let them just behave like all
other arguments.

Consider that if we do that, then someone will need to disambiguate with:
object.safe
which is ambiguous:
a.b .c x = 3;
or is it:
a .b.c x = 3;
?
Another problem is it pushes off recognition of safe from the parser to
the semantic analyzer. This has unknown forward reference complications.

How didn't see that coming. I never was a big fan of .identifier syntax
for module level stuff.
However, you example isn't quite correct. Attributes are for symbols,
and your example don't create any new symbol.
Let's consider a.b .c d = 3;
Now, we have several option to disambiguate that. The first, obvious one
is to use () : (a.b) .c d = 3; .
When not using (), the compiler understand this as (a.b.c) d = 3; which
is an error.
Another option is to use auto : a.b auto d = .c(3);
Anyway, I don't expect this to break too much code, if any.

I we were to allow for foobar style UDA then "safe" would
have to be
a reserved
keyword somehow. Otherwise I do not know what this would mean:
struct safe { }
safe void foobar() { }

Yes, I agree this is a significant problem.

I think it's solvable. The basic approach would be to plop
types "safe", "nothrow" etc. in object.di and then let them
just behave like all other arguments.

The original argument that the in front of safe is a way to
prevent introducing new keywords is all gone then since "safe"
becomes a normal symbol which is reserved in the library and in
the compiler to let it do its magic.
Then safe could just as well be a normal builtin storage class
called "safe".
* Plopping types "safe","nothrow" etc. into object.di would be a
breaking change.
* Making safe, nothrow into keywords called "safe", "nothrow"
would be breaking change.
The latter would be the cleanest cut and not have the
semantic/parse stage problems that Walter mentioned.
Another option would to enforce parenthesis (safe) for UDA which
would make it less nice for the eyes to look at.
/Jonas

I we were to allow for foobar style UDA then "safe" would
have to be
a reserved
keyword somehow. Otherwise I do not know what this would
mean:
struct safe { }
safe void foobar() { }

Yes, I agree this is a significant problem.

I think it's solvable. The basic approach would be to plop
types "safe", "nothrow" etc. in object.di and then let them
just behave like all other arguments.

The original argument that the in front of safe is a way to
prevent introducing new keywords is all gone then since "safe"
becomes a normal symbol which is reserved in the library and in
the compiler to let it do its magic.
Then safe could just as well be a normal builtin storage class
called "safe".
* Plopping types "safe","nothrow" etc. into object.di would be
a breaking change.
* Making safe, nothrow into keywords called "safe", "nothrow"
would be breaking change.
The latter would be the cleanest cut and not have the
semantic/parse stage problems that Walter mentioned.
Another option would to enforce parenthesis (safe) for UDA
which would make it less nice for the eyes to look at.
/Jonas

I we were to allow for foobar style UDA then "safe" would have to be
a reserved
keyword somehow. Otherwise I do not know what this would mean:
struct safe { }
safe void foobar() { }

Yes, I agree this is a significant problem.

I think it's solvable. The basic approach would be to plop types
"safe", "nothrow" etc. in object.di and then let them just behave like
all other arguments.

The original argument that the in front of safe is a way to prevent
introducing new keywords is all gone then since "safe" becomes a normal
symbol which is reserved in the library and in the compiler to let it do
its magic.
Then safe could just as well be a normal builtin storage class called
"safe".
* Plopping types "safe","nothrow" etc. into object.di would be a
breaking change.
* Making safe, nothrow into keywords called "safe", "nothrow" would be
breaking change.
The latter would be the cleanest cut and not have the semantic/parse
stage problems that Walter mentioned.
Another option would to enforce parenthesis (safe) for UDA which would
make it less nice for the eyes to look at.
/Jonas

nothrow is already a keyword (which is really inconsistent). I'm not
sure what it does buy us, and both safe and nothrow are good candidates
for lib implementation rather than compiler support.

nothrow is already a keyword (which is really inconsistent). I'm not
sure what it does buy us, and both safe and nothrow are good candidates
for lib implementation rather than compiler support.

That requires that the compiler exposes all sorts of
statistical data for every statement. E.g. to check if nothrow
is violated you have to find statements that throw something
and then check if there is a catch block around that, that
catches it. If a statement is a function call, you would
ask the compiler if that function throws. (In particular if it
is a templated function with deduced 'nothrow' and ' safe').
And there you are at the point that you just duplicated the
compiler code in the library.
--
Marco

nothrow is already a keyword (which is really inconsistent). I'm not
sure what it does buy us, and both safe and nothrow are good candidates
for lib implementation rather than compiler support.

That requires that the compiler exposes all sorts of
statistical data for every statement. E.g. to check if nothrow
is violated you have to find statements that throw something
and then check if there is a catch block around that, that
catches it. If a statement is a function call, you would
ask the compiler if that function throws. (In particular if it
is a templated function with deduced 'nothrow' and ' safe').
And there you are at the point that you just duplicated the
compiler code in the library.

Not duplicated, but moved - which results in a simpler compiler
implementation, definitely a good thing.
Of course those AST analytics/maccro functionality has to be added in
return, but since this has a much broader scope and would make other
features (string mixins) obsolete, even that is not quite clear in terms
of weight as a counter argument.
Anyway, I surely wouldn't expect this to happen anytime soon, but
keeping this path open seems like a wise decision - it's a great
opportunity to remove/not add features from/to the language without
trading functinality or even syntax.

For User Defined Attributes.
In the north corner we have the current champeeeeon:
-------
[ ArgumentList ]
Pros:
precedent with C#
looks nice
Cons:
not so greppable
parsing ambiguity with [array literal].func();
------
In the south corner, there's the chaaaaallenger:
( ArgumentList )
Pros:
looks like existing attribute syntax
no parsing problems
Cons:
not as nice looking
------
No hitting below the belt! Let the games begin!

I prefer the (list) syntax because we already have attributes
and that is what we are all familiar with.
Regards

For User Defined Attributes.
In the north corner we have the current champeeeeon:
-------
[ ArgumentList ]
Pros:
precedent with C#
looks nice
Cons:
not so greppable
parsing ambiguity with [array literal].func();
------
In the south corner, there's the chaaaaallenger:
( ArgumentList )
Pros:
looks like existing attribute syntax
no parsing problems
Cons:
not as nice looking
------
No hitting below the belt! Let the games begin!

Already too late to the party. I join my voice to the () group.
--
Paulo

(attribute) looks prettier to me, and with the other pros I
think it's the clear winner. I always though C#'s [Attribute]
syntax didn't make a lot of sense. I'm also for: attr1 attr2
int i; type syntax if that was being discussed previously
(someone mentioned it). It would be very consistent with what's
already there.
Congrats on Attributes, BTW! Great news :)

For User Defined Attributes.
In the north corner we have the current champeeeeon:
-------
[ ArgumentList ]
Pros:
precedent with C#
looks nice
Cons:
not so greppable
parsing ambiguity with [array literal].func();
------
In the south corner, there's the chaaaaallenger:
( ArgumentList )
Pros:
looks like existing attribute syntax
no parsing problems
Cons:
not as nice looking
------
No hitting below the belt! Let the games begin!

About () vs [] the key point to me is that this is consistent with
tuple syntax (which don't exists yet \o/).
The important point to me is that a is allowed.

For User Defined Attributes.
In the north corner we have the current champeeeeon:
-------
[ ArgumentList ]
Pros:
precedent with C#
looks nice
Cons:
not so greppable
parsing ambiguity with [array literal].func();
------
In the south corner, there's the chaaaaallenger:
( ArgumentList )
Pros:
looks like existing attribute syntax
no parsing problems
Cons:
not as nice looking
------
No hitting below the belt! Let the games begin!

() with required ().
So we will still have place for new language attributes like rox
etc ;)

For User Defined Attributes.
In the north corner we have the current champeeeeon:
-------
[ ArgumentList ]
Pros:
precedent with C#
looks nice
Cons:
not so greppable
parsing ambiguity with [array literal].func();
------
In the south corner, there's the chaaaaallenger:
( ArgumentList )
Pros:
looks like existing attribute syntax
no parsing problems
Cons:
not as nice looking
------
No hitting below the belt! Let the games begin!

() with required ().
So we will still have place for new language attributes like rox etc ;)