November 07, 2012
On 11/7/2012 3:06 PM, Kapps wrote:
> I do agree however with preventing any built-in types / literals being used as
> an annotation. It's just not safe, completely goes around the module system, and
> is abused in the same way as it would be with C++ exceptions. In C# for example,
> all attributes are classes derived from Attribute. This makes things a bit more
> obvious, allows a common base type (probably not needed in D because it's done
> at compile-time), but is rather hackish in my opinion (plus, in D you may want
> structs as attributes?). I definitely would like to see something like the
> @attribute suggestion though. Using types not meant to be used as attributes as
> attributes is dangerous and leads to conflicts when people want it to mean
> different things. What does '@Vector3f(1, 1, 1) int a' even mean? What if people
> use it to mean different things? It's just as confusing as '@3 int a'.

See new thread I started on this in digitalmars.D.
November 07, 2012
On Wednesday, 7 November 2012 at 23:17:24 UTC, Walter Bright wrote:
> Doesn't putting compiler hooks in for them make them inherently global?

One of the previous threads put forth something like this:

template MyAttribute(alias subject, T... arguments) { /* some implementation */

The attribute is a template that replaces the declaration. So you type:

[MyAttribute("foo")]
class Something {}


And the compiler rewrites that to:

class __anonymous_Something {}

alias Something = MyAttribute!(__anonymous_Something, "foo");



... or something like that. I'm going off memory here. But then you can use the template to do whatever you'd normally do with a template.

For some reason this feels incomplete to me. I know one of those proposals enabled something we can't really do now, whereas what I described here of course *can* be done now.
November 08, 2012
Le 08/11/2012 00:17, Walter Bright a écrit :
> On 11/7/2012 2:40 PM, deadalnix wrote:
>> Java is mostly compile time (and optionally runtime). See
>> http://projectlombok.org/ for what can be done at compile time with
>> attributes +
>> compiler hooks.
>
> Doesn't putting compiler hooks in for them make them inherently global?
>

The hook is associated to a given attribute so no it doesn't.
November 08, 2012
On 11/7/2012 4:12 PM, deadalnix wrote:
> Le 08/11/2012 00:17, Walter Bright a écrit :
>> On 11/7/2012 2:40 PM, deadalnix wrote:
>>> Java is mostly compile time (and optionally runtime). See
>>> http://projectlombok.org/ for what can be done at compile time with
>>> attributes +
>>> compiler hooks.
>>
>> Doesn't putting compiler hooks in for them make them inherently global?
>>
>
> The hook is associated to a given attribute so no it doesn't.

Yes, that makes the attribute global.
November 08, 2012
On 2012-11-08 00:43, Adam D. Ruppe wrote:

> One of the previous threads put forth something like this:
>
> template MyAttribute(alias subject, T... arguments) { /* some
> implementation */
>
> The attribute is a template that replaces the declaration. So you type:
>
> [MyAttribute("foo")]
> class Something {}
>
>
> And the compiler rewrites that to:
>
> class __anonymous_Something {}
>
> alias Something = MyAttribute!(__anonymous_Something, "foo");
>
>
>
> ... or something like that. I'm going off memory here. But then you can
> use the template to do whatever you'd normally do with a template.
>
> For some reason this feels incomplete to me. I know one of those
> proposals enabled something we can't really do now, whereas what I
> described here of course *can* be done now.

Seems like a poor man's replacement for macro annotations:

http://scalamacros.org/future.html

-- 
/Jacob Carlborg
November 08, 2012
On 2012-11-08 02:49, Walter Bright wrote:

> Yes, that makes the attribute global.

I don't actually know how this works in Java but if you are forced to use the fully qualified name for the attribute it won't make the attribute global.

-- 
/Jacob Carlborg
November 08, 2012
On 2012-11-07 23:20, Walter Bright wrote:

> There's another aspect to this.
>
> D's UDAs are a purely compile time system, attaching arbitrary metadata
> to specific symbols. The other UDA systems I'm aware of appear to be
> runtime systems.
>
> This implies the use cases will be different - how, I don't really know.
> But I don't know of any other compile time UDA system. Experience with
> runtime systems may not be as applicable.
>
> Another interesting data point is CTFE. C++11 has CTFE, but it was
> deliberately crippled and burdened with "constexpr". From what I read,
> this was out of fear that it would turn out to be an overused and
> overabused feature. Of course, this turned out to be a large error.
>
> One last thing. Sure, string attributes can (and surely would be) used
> for different purposes in different libraries. The presumption is that
> this would cause a conflict. But would it? There are two aspects to a
> UDA - the attribute itself, and the symbol it is attached to. In order
> to get the UDA for a symbol, one has to look up the symbol.

This is what I start to like less and less about the current implementation of UDA. There is no actual attribute. There is the symbol with a bunch of random attached values.

I want to be able to do something like this:

module bar;

@attribute struct foo
{
    string name;
}

@foo int a;

alias Tuple!(__traits(getAttributes, foo)) TP;

enum bool yes = hasAttribute!(bar.foo);

static if (yes)
    enum foo attr = getAttribute!(bar.foo);

The last two could actually be library functions.

> There isn't
> a global repository of symbols in D. You'd have to say "I want to look
> in module X for symbols." Why would you look in module X for an
> attribute that you have no reason to believe applies to symbols from X?
> How would an attribute for module X's symbols leak out of X on their own?

Have you ever heard of libraries. You can pass a symbol as an alias parameter to a function of a completely different library.

> It's not quite analogous to exceptions, because arbitrary exceptions
> thrown from module X can flow through your code even though you have no
> idea module X even exists.
>


-- 
/Jacob Carlborg
November 08, 2012
On Thursday, 8 November 2012 at 07:35:30 UTC, Jacob Carlborg wrote:
> On 2012-11-07 23:20, Walter Bright wrote:
>
> module bar;
>
> @attribute struct foo
> {
>     string name;
> }
>
> @foo int a;
>
> alias Tuple!(__traits(getAttributes, foo)) TP;
>
> enum bool yes = hasAttribute!(bar.foo);
>
> static if (yes)
>     enum foo attr = getAttribute!(bar.foo);
>
> The last two could actually be library functions.

Could you explain why it is impossible without complicating the current state of things? I gave it a quick try and it seems to work reasonably well (a proper implementation will be more involved due to compiler bugs and language issues irrelevant to this discussion):

// library that defines attribute accessors
module library;
import std.typetuple;

template TypeOf(alias symbol)
{
    alias typeof(symbol) TypeOf;
}

template indexOfAttribute(alias symbol, alias attrType)
{
    alias staticMap!(TypeOf, __traits(getAttributes, symbol)) attrTypes;
    enum indexOfAttribute = staticIndexOf!(attrTypes, attrType);
}

template hasAttribute(alias symbol, alias attrType)
{
    enum hasAttribute = indexOfAttribute!(symbol, attrType) != -1;
}

template getAttribute(alias symbol, alias attrType)
{
    alias TypeTuple!(__traits(getAttributes, symbol)) attrs;
    enum getAttribute = attrs[indexOfAttribute!(symbol, attrType)];
}

// module that defines a foo attribute
module a;

struct foo
{
    string name;
}

[foo("a's foo")] int a;

// an unrelated module that defines its own foo
module b;

import library;
import a;

struct foo
{
    string name;
}

[foo("b's foo")] int b;

static if (hasAttribute!(b, foo))
{
    alias getAttribute!(b, foo) t;
    static assert(getAttribute!(b, foo).name == "b's foo");
}

static if (hasAttribute!(a.a, a.foo))
    static assert(getAttribute!(a.a, a.foo).name == "a's foo");

void main()
{
}







November 08, 2012
On 11/8/12 12:20 AM, Walter Bright wrote:
> One last thing. Sure, string attributes can (and surely would be) used
> for different purposes in different libraries. The presumption is that
> this would cause a conflict. But would it? There are two aspects to a
> UDA - the attribute itself, and the symbol it is attached to. In order
> to get the UDA for a symbol, one has to look up the symbol. There isn't
> a global repository of symbols in D. You'd have to say "I want to look
> in module X for symbols." Why would you look in module X for an
> attribute that you have no reason to believe applies to symbols from X?
> How would an attribute for module X's symbols leak out of X on their own?

Actually there's a stark difference between string attributes and symbol attributes (assuming I understand the point): attribute lookup and potential ambiguity are solved using regular symbol lookup and potential ambiguity - by using name resolution. In contrast, string attributes have no other resolution mechanism than string comparison.

So now say two modules moda and modb define an attribute "untainted" with distinct semantics. If "untainted" is a string, there's no way out of this - the modules simply cannot work together. In contrast, if untainted is a regular symbol, it will cause ambiguity errors that are solvable by using qualified lookup a la moda.untainted and modb.untainted.


Andrei



November 08, 2012
On Thursday, 8 November 2012 at 09:08:23 UTC, Max Samukha wrote:
>     alias getAttribute!(b, foo) t;

Ignore that line.