January 04, 2013
OK, now that 2.061 is out, we have User-Defined Attributes (UDAs).

Except, there is no doc on them, no explanation, nothing. For people who did not follow the monstrous threads in November, it's as if UDA do not exist.

Myself, I upgraded from 2.060 only yesterday, and I never used them. Heck, I do not even know their syntax. This thread is for people like me, who wonder what UDA are, and what can be done with them.

Jacob Carlborg wrote documentation, but it's not merged into dlang.org yet, AFAICT. Here it is:

https://github.com/jacob-carlborg/d-programming-language.org/commit/bddbdf18353203ba12d8e0e44391e8b6a031b91a

Here is the executive summary:

User Defined Attributes (UDA) are compile time expressions that can be attached to a declaration. These attributes can then be queried, extracted, and manipulated at compile time. There is no runtime component to them.

Syntax:

@(3) int a;
@("string", 7) int b;

enum Foo;
@Foo int c;

struct Bar
{
    int x;
}

@Bar(3) int d;


From that, I get we can put any CT symbol (even a value) as an attribute. I thought we were restricted to user defined types.

To query them, use __traits(getAttributes, symbol)


@('c') string s;
__traits(getAttributes, s)

this gives a tuple of attributes, that can be manipulated as a template tuple parameter (the 'raw' tuples).



Jacob, you doc says UDA are (grammatically) treated as storage classes. Can we do:

class C {
    @(3, "hello"):
        int a;
        double d;
}

And get both a and d with the same UDAs?
[Answer: silly me, I have 2.061. Yes, that works, both C.a and C.d have (3, "hello") as an attribute]

My own rapid reading tells me we will rapidly need good tuple manipulations templates in Phobos. We have mapping and filtering (I guess?), but overloading, discarding, dropping and folding will be needed also.


January 04, 2013
On 2013-01-04 16:45, Philippe Sigaud wrote:
> OK, now that 2.061 is out, we have User-Defined Attributes (UDAs).
>
> Except, there is no doc on them, no explanation, nothing. For people who
> did not follow the monstrous threads in November, it's as if UDA do not
> exist.
>
> Myself, I upgraded from 2.060 only yesterday, and I never used them.
> Heck, I do not even know their syntax. This thread is for people like
> me, who wonder what UDA are, and what can be done with them.
>
> Jacob Carlborg wrote documentation, but it's not merged into dlang.org
> yet, AFAICT. Here it is:
>
> https://github.com/jacob-carlborg/d-programming-language.org/commit/bddbdf18353203ba12d8e0e44391e8b6a031b91a

And here, nicely rendered:

https://dl.dropbox.com/u/18386187/attribute.html#uda

There's also documentation for the Traits section but nothing which isn't available on the Attribute section.

-- 
/Jacob Carlborg
January 04, 2013
On 2013-01-04 16:45, Philippe Sigaud wrote:

> Syntax:
>
> @(3) int a;
> @("string", 7) int b;
>
> enum Foo;
> @Foo int c;
>
> struct Bar
> {
>      int x;
> }
>
> @Bar(3) int d;
>
>
>  From that, I get we can put any CT symbol (even a value) as an
> attribute. I thought we were restricted to user defined types.

No, basically anything that can be put in a tuple can be used as an UDA. I'm wondering if we want to add a meta attribute to Phobos or druntime (object.d). Some thing like:

enum attribute;

@attribute struct Foo { }

Now, by convention "Foo" is an attribute and should only be used as an attribute. We could also add some functions to std.traits for querying UDA that takes advantage of this attribute.

-- 
/Jacob Carlborg
January 04, 2013
On Friday, 4 January 2013 at 15:45:21 UTC, Philippe Sigaud wrote:
>
> My own rapid reading tells me we will rapidly need good tuple manipulations templates in Phobos.

s/we will rapidly need/we have needed for years

January 04, 2013
So, I'm testing how to transfer UDA from one symbol to another.

```
auto transferAttributes(alias origin, To)(To t)
{
    @(__traits(getAttributes, origin)) To temp = t;
    pragma(msg, __traits(getAttributes, temp));
    return temp;
}

void main()
{
    @(3, "hello") int i = 10;
    writeln("[",__traits(getAttributes, i), "]");

    double d = 3.14;
    auto d2 = transferAttributes!(i)(d);
    // Doesn't work
    writeln("[",__traits(getAttributes, d2), "]");

    // Works:
    @(__traits(getAttributes, i)) double d3 = 3.14;
    writeln("[",__traits(getAttributes, d3), "]");
}
```

Begins at the end: d3 (a double) indeed ends up as having i (an int) attributes. All is well and good.

But transferAttributes does not work: inside its scope, temp has the attributes from origin, but not when it gets out.

Also, dropping the auto return is not accepted by the compiler, even though it seems natural for me:

@(__traits(getAttributes, origin)) To transferAttributes(alias origin, To)(To t)
{
    @(__traits(getAttributes, origin)) To temp = t;
...

'origin' is a template parameter and should be reachable to determine the return type.

January 04, 2013
On Friday, 4 January 2013 at 16:04:59 UTC, Philippe Sigaud wrote:
> So, I'm testing how to transfer UDA from one symbol to another.
>
> ```
> auto transferAttributes(alias origin, To)(To t)
> {
>     @(__traits(getAttributes, origin)) To temp = t;
>     pragma(msg, __traits(getAttributes, temp));
>     return temp;
> }
>
> void main()
> {
>     @(3, "hello") int i = 10;
>     writeln("[",__traits(getAttributes, i), "]");
>
>     double d = 3.14;
>     auto d2 = transferAttributes!(i)(d);

transferAttributes attaches the attributes to the local declaration. I'd be surprised if they were copied to the outer declaration. Or did you mean attributing the return *type*?

>     // Doesn't work
>     writeln("[",__traits(getAttributes, d2), "]");
>
>     // Works:
>     @(__traits(getAttributes, i)) double d3 = 3.14;
>     writeln("[",__traits(getAttributes, d3), "]");
> }
> ```
>
> Begins at the end: d3 (a double) indeed ends up as having i (an int) attributes. All is well and good.
>
> But transferAttributes does not work: inside its scope, temp has the attributes from origin, but not when it gets out.
>
> Also, dropping the auto return is not accepted by the compiler, even though it seems natural for me:
>
> @(__traits(getAttributes, origin)) To transferAttributes(alias origin, To)(To t)
> {
>     @(__traits(getAttributes, origin)) To temp = t;
> ...
>
> 'origin' is a template parameter and should be reachable to determine the return type.

That's a bug. Anyway, you are attributing the function declaration here, not the return type, which is another problem as it looks we do not have a syntax for that and "auto" is required:

auto foo()
{
    @attr struct S {}
    return S.init;
}





January 04, 2013
Max:

> transferAttributes attaches the attributes to the local declaration. I'd be surprised if they were copied to the outer declaration. Or did you mean attributing the return *type*?


The declaration. The type, I guess I'd use an alias. Though, I guess the alias syntax limitations would probably forbid that.

So yes, the local declaration is attributed, that works. How do I propagate the attribute to the returned value?


Also, dropping the auto return is not accepted by the compiler, even though
>> it seems natural for me:
>>
>> @(__traits(getAttributes, origin)) To transferAttributes(alias origin,
>> To)(To t)
>> {
>>     @(__traits(getAttributes, origin)) To temp = t;
>> ...
>>
>> 'origin' is a template parameter and should be reachable to determine the return type.
>>
>
> That's a bug.


Already filed?



> Anyway, you are attributing the function declaration here, not the return type


Hmm. Would @(attr) { ReturnType } functionName (...)  work?




> , which is another problem as it looks we do not have a syntax for that and "auto" is required:
>
> auto foo()
> {
>     @attr struct S {}
>     return S.init;
> }
>
>


January 04, 2013
On Friday, 4 January 2013 at 17:11:04 UTC, Philippe Sigaud wrote:
> The declaration. The type, I guess I'd use an alias. Though, I guess the
> alias syntax limitations would probably forbid that.
>
> So yes, the local declaration is attributed, that works. How do I propagate
> the attribute to the returned value?

I think you cannot.

>
>
> Also, dropping the auto return is not accepted by the compiler, even though
>>> it seems natural for me:
>>>
>>> @(__traits(getAttributes, origin)) To transferAttributes(alias origin,
>>> To)(To t)
>>> {
>>>     @(__traits(getAttributes, origin)) To temp = t;
>>> ...
>>>
>>> 'origin' is a template parameter and should be reachable to determine the
>>> return type.
>>>
>>
>> That's a bug.
>
>
> Already filed?

Don't think so.

>
>
>
>> Anyway, you are attributing the function declaration here, not the return
>> type
>
>
> Hmm. Would @(attr) { ReturnType } functionName (...)  work?
>

It looks we simply cannot modify existing declarations with UDAs.

@(attr) alias foo = bar; // @(attr) is ignored.

It is inconsistent with builtin attributes, which can create modified declarations out of existing ones. I am not sure whether it is a real problem.





January 04, 2013
On Friday, 4 January 2013 at 15:45:21 UTC, Philippe Sigaud wrote:
> OK, now that 2.061 is out, we have User-Defined Attributes (UDAs).
>
> Except, there is no doc on them, no explanation, nothing. For people who did not follow the monstrous threads in November, it's as if UDA do not exist.

> ...

> Here is the executive summary:
>
> User Defined Attributes (UDA) are compile time expressions that can be attached to a declaration. These attributes can then be queried, extracted, and manipulated at compile time. There is no runtime component to them.

 This is sorta like tuples; But from the brief summaries I cannot fully understand how or where they would be used. I understand some attributes can be made and added that some compilers may use (@noreturn as an example), but outside of the compiler I'd need an example of how to make use of them.

 Since there's no runtime component, then aside from carrying a tuple and some information forward at compile-time, what else can it do? How would you use it? Are there any special tuple formats that give information to automatically be included/compiled into the structs/classes without having to resort to mixins?



 Curiously enough it seems like @clone would be a useful example. Let's assume we want to write @clone, it's meaning that rather than writing a custom postblit to it's done automatically.

 struct S {
   string identifier;
   int value;
   string[] attributes; // @clone

   this(this) {attributes = attributes.dup;}
 }

 Normally you'd write a this(this) as above, but if we used UDA's how could it be used/implemented?
January 04, 2013
On 1/4/2013 9:48 AM, Max Samukha wrote:
> It looks we simply cannot modify existing declarations with UDAs.
>
> @(attr) alias foo = bar; // @(attr) is ignored.

alias provides a way to provide an alternate name for a symbol. It wouldn't be an alternate name if it had different attributes. Trying to make such work would have serious semantic consequences.

Hence, no, you cannot use alias to modify the attributes.

« First   ‹ Prev
1 2 3 4 5 6 7
Top | Discussion index | About this forum | D home