View mode: basic / threaded / horizontal-split · Log in · Help
January 04, 2013
So, User-Defined Attributes
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
Re: So, User-Defined Attributes
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
Re: So, User-Defined Attributes
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
Re: So, User-Defined Attributes
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
Re: So, User-Defined Attributes
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
Re: So, User-Defined Attributes
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
Re: So, User-Defined Attributes
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
Re: So, User-Defined Attributes
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
Re: So, User-Defined Attributes
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
Re: So, User-Defined Attributes
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
Top | Discussion index | About this forum | D home