April 06, 2012
On 06-04-2012 08:47, Walter Bright wrote:
> On 4/5/2012 5:00 AM, Manu wrote:
>  > C# and Java both have attributes, following these established design
> patterns, I
>  > don't think there should be any mystery over how they should be
> implemented.
>
> I was thinking of something along the lines of what has been proposed
> here earlier:
>
> @attr(identifier = expression)
>
> as a storage class, like:
>
> @attr(foo = bar + 1) int x;
>
> and then:
>
> __traits(hasAttribute, x, foo)
>
> would return true, and:
>
> __traits(getAttribute, x, foo)
>
> would return the expression (bar+1). The expression would be
> compile-time only, evaluated at the point of declaration.
>
> The implementation is simple enough, just attach to each symbol an array
> of (identifier,expression) pairs.
>
> You could also omit the expression, and just have:
>
> @attr(bar) int y;

I think this is mostly reasonable. I assume that it would be possible to use the comma operator to attach multiple values to it? I.e.:

@attr(foo = bar, baz) int x;

My only other concern is what Kapps pointed out about larger projects and overlapping attribute names.

-- 
- Alex
April 06, 2012
On Friday, 6 April 2012 at 06:47:56 UTC, Walter Bright wrote:
> On 4/5/2012 5:00 AM, Manu wrote:
> > C# and Java both have attributes, following these established
> design patterns, I
> > don't think there should be any mystery over how they should
> be implemented.
>
> I was thinking of something along the lines of what has been proposed here earlier:
>
>   @attr(identifier = expression)
>
> as a storage class, like:
>
>   @attr(foo = bar + 1) int x;
>
> and then:
>
>   __traits(hasAttribute, x, foo)
>
> would return true, and:
>
>   __traits(getAttribute, x, foo)
>
> would return the expression (bar+1). The expression would be compile-time only, evaluated at the point of declaration.
>
> The implementation is simple enough, just attach to each symbol an array of (identifier,expression) pairs.
>
> You could also omit the expression, and just have:
>
>   @attr(bar) int y;

I like it. Perhaps

    @attr(bar)

could be equivalent to

    @attr(bar = true)

so you don't get any weird failure state for __traits(getAttribute?

April 06, 2012
On 4/6/2012 12:17 AM, Kapps wrote:
> I like it for the most part. One thing I'd like to see is placing multiple
> attributes both by using multiple @attr()'s, and by using comma separated
> identifier/expression pairs inside a single @attr. In other words, the following
> two declarations would be identical.
>
> @attr(Description = "Blah", ReadOnly)
> int ID;
>
> @attr(Description = "Blah")
> @attr(ReadOnly)
> int ID;

Yes, that makes sense.

> My only concerns:
>
> First, @attr() is a little verbose / not exactly pretty. This isn't really a big
> issue, since attributes aren't exactly piled on and it makes it easy to tell
> what's going on. It is a little uglier than in other languages however.

Could do:

   [[name = value]]

I suppose. Not sure what's better.


> Secondly, from what I can tell it's an arbitrary key value combo. What would
> happen if you're working on a larger project and two unrelated libraries try to
> use the same attribute name to mean different things? With the module system
> this issue doesn't exist since you have to import it and can
> selectively/privately do so, but from what I understand the method you're
> proposing doesn't declare the attribute itself at all. Am I just
> misunderstanding this part?

Good question. I don't have experience using attributes, so I don't know if this would be a problem. Keep in mind that the attribute lookup will only be done for a particular symbol, there won't be any global lookup.
April 06, 2012
On 4/6/2012 12:31 AM, Bernard Helyer wrote:
> I like it. Perhaps
>
> @attr(bar)
>
> could be equivalent to
>
> @attr(bar = true)
>
> so you don't get any weird failure state for __traits(getAttribute?


That's what the hasAttribute is for.
April 06, 2012
On 06-04-2012 09:32, Walter Bright wrote:
> On 4/6/2012 12:17 AM, Kapps wrote:
>> I like it for the most part. One thing I'd like to see is placing
>> multiple
>> attributes both by using multiple @attr()'s, and by using comma separated
>> identifier/expression pairs inside a single @attr. In other words, the
>> following
>> two declarations would be identical.
>>
>> @attr(Description = "Blah", ReadOnly)
>> int ID;
>>
>> @attr(Description = "Blah")
>> @attr(ReadOnly)
>> int ID;
>
> Yes, that makes sense.
>
>> My only concerns:
>>
>> First, @attr() is a little verbose / not exactly pretty. This isn't
>> really a big
>> issue, since attributes aren't exactly piled on and it makes it easy
>> to tell
>> what's going on. It is a little uglier than in other languages however.
>
> Could do:
>
> [[name = value]]
>
> I suppose. Not sure what's better.
>
>
>> Secondly, from what I can tell it's an arbitrary key value combo. What
>> would
>> happen if you're working on a larger project and two unrelated
>> libraries try to
>> use the same attribute name to mean different things? With the module
>> system
>> this issue doesn't exist since you have to import it and can
>> selectively/privately do so, but from what I understand the method you're
>> proposing doesn't declare the attribute itself at all. Am I just
>> misunderstanding this part?
>
> Good question. I don't have experience using attributes, so I don't know
> if this would be a problem. Keep in mind that the attribute lookup will
> only be done for a particular symbol, there won't be any global lookup.

It actually can be a problem. In .NET land, there are many attributes across many projects (and even in the framework itself) with the same names. It turns out that regular namespace lookup rules alleviate this problem.

-- 
- Alex
April 06, 2012
On 06-04-2012 09:31, Bernard Helyer wrote:
> On Friday, 6 April 2012 at 06:47:56 UTC, Walter Bright wrote:
>> On 4/5/2012 5:00 AM, Manu wrote:
>> > C# and Java both have attributes, following these established
>> design patterns, I
>> > don't think there should be any mystery over how they should
>> be implemented.
>>
>> I was thinking of something along the lines of what has been proposed
>> here earlier:
>>
>> @attr(identifier = expression)
>>
>> as a storage class, like:
>>
>> @attr(foo = bar + 1) int x;
>>
>> and then:
>>
>> __traits(hasAttribute, x, foo)
>>
>> would return true, and:
>>
>> __traits(getAttribute, x, foo)
>>
>> would return the expression (bar+1). The expression would be
>> compile-time only, evaluated at the point of declaration.
>>
>> The implementation is simple enough, just attach to each symbol an
>> array of (identifier,expression) pairs.
>>
>> You could also omit the expression, and just have:
>>
>> @attr(bar) int y;
>
> I like it. Perhaps
>
> @attr(bar)
>
> could be equivalent to
>
> @attr(bar = true)
>
> so you don't get any weird failure state for __traits(getAttribute?
>

While I understand the rationale, that seems a bit too "magic"...

-- 
- Alex
April 06, 2012
On 06-04-2012 08:47, Walter Bright wrote:
> On 4/5/2012 5:00 AM, Manu wrote:
>  > C# and Java both have attributes, following these established design
> patterns, I
>  > don't think there should be any mystery over how they should be
> implemented.
>
> I was thinking of something along the lines of what has been proposed
> here earlier:
>
> @attr(identifier = expression)
>
> as a storage class, like:
>
> @attr(foo = bar + 1) int x;
>
> and then:
>
> __traits(hasAttribute, x, foo)
>
> would return true, and:
>
> __traits(getAttribute, x, foo)
>
> would return the expression (bar+1). The expression would be
> compile-time only, evaluated at the point of declaration.
>
> The implementation is simple enough, just attach to each symbol an array
> of (identifier,expression) pairs.
>
> You could also omit the expression, and just have:
>
> @attr(bar) int y;

Also, by storage class do you mean it will work only on fields? Attributes are very useful on many different kinds of declarations, so if that's the case, I think that would be too limiting.

-- 
- Alex
April 06, 2012
On 4/6/2012 12:42 AM, Alex Rønne Petersen wrote:
> Also, by storage class do you mean it will work only on fields?

No. Storage classes work on fields, functions, and variables.

April 06, 2012
On 4/6/2012 12:35 AM, Alex Rønne Petersen wrote:
> It actually can be a problem. In .NET land, there are many attributes across
> many projects (and even in the framework itself) with the same names. It turns
> out that regular namespace lookup rules alleviate this problem.


Perhaps a better scheme is:

   enum foo = 3;

   ...

   @attr(foo) int x;

That way, foo will follow all the usual rules.

April 06, 2012
On 06-04-2012 09:47, Walter Bright wrote:
> On 4/6/2012 12:42 AM, Alex Rønne Petersen wrote:
>> Also, by storage class do you mean it will work only on fields?
>
> No. Storage classes work on fields, functions, and variables.
>

What about type declarations? I think those ought to be supported too. E.g. it makes sense to mark an entire type as @attr(serializable) (or the inverse).

-- 
- Alex