User Defined Attributes

2012-11-06 Thread Walter Bright

References:

http://www.digitalmars.com/d/archives/digitalmars/D/Custom_attributes_again_163042.html

http://www.digitalmars.com/d/archives/digitalmars/D/custom_attribute_proposal_yeah_another_one_163246.html

Inspired by a gallon of coffee, I decided to get it implemented. It's simple, 
based on what D already does (CTFE and heterogeneous tuples), easy to implement, 
easy to understand, and doesn't break anything. It should do everything asked 
for in the above references (except it's not a type constructor).


You can download it here and try it out:

http://ftp.digitalmars.com/dmd2beta.zip

As a bonus, that beta also can generate Win64 executables, and you can even 
symbolically debug them with VS! (Thanks to Rainer Schütze for his invaluable 
help with that).


Here's the rather skimpy and lame spec I banged out:
=
User Defined Attributes
---

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.

Grammatically, a UDA is a StorageClass:

StorageClass:
UserDefinedAttribute

UserDefinedAttribute:
[ ArgumentList ]

And looks like:

[ 3 ] int a;
[ string, 7 ]: int b;

If there are multiple UDAs in scope for a declaration, they are concatenated:

[ 1 ] {
   [ 2 ] int a;// has UDA's [1,2]
   [ string ] int b; // has UDA's [1,string]
}

UDA's can be extracted into an expression tuple using __traits:

[ 'c' ] string s;
pragma(msg, __traits(getAttributes, s));

prints:

tuple('c')

If there are no user defined attributes for the symbol, an empty tuple is 
returned.
The expression tuple can be turned into a manipulatable tuple:

  template Tuple(T...) {
alias T Tuple;
  }

  enum EEE = 7;
  [hello] struct SSS { }
  [3] { [4][EEE][SSS] int foo; }

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

  pragma(msg, TP);
  pragma(msg, TP[2]);

prints:

  tuple(3,4,7,(SSS))
  7

and of course the tuple types can be used to declare things:

  TP[3] a;// a is declared as an SSS

The attribute of the type name is not the same as the attribute of the variable:

  pragma(msg, __traits(getAttributes, typeof(a));

prints:

tuple(hello)

Of course, the real value of UDA's is to be able to create user defined types 
with
specific values. Having attribute values of basic types does not scale.
The attribute tuples can be manipulated like any other tuple, and
can be passed as the argument list to a template.

Whether the attributes are values or types is up to the user, and whether later
attributes accumulate or override earlier ones is also up to how the user 
interprets them.


Re: User Defined Attributes

2012-11-06 Thread Tove

On Tuesday, 6 November 2012 at 07:55:51 UTC, Walter Bright wrote:

References:

http://www.digitalmars.com/d/archives/digitalmars/D/Custom_attributes_again_163042.html

http://www.digitalmars.com/d/archives/digitalmars/D/custom_attribute_proposal_yeah_another_one_163246.html

Inspired by a gallon of coffee, I decided to get it 
implemented. It's simple, based on what D already does (CTFE


[*drool*, totally perfect awesomeness] Thanks!



Re: User Defined Attributes

2012-11-06 Thread Sönke Ludwig
Wow, that's a surprise! Just yesterday I was thinking that it would be
really nice to have them for a piece of code ;)

But shouldn't we keep the syntax closer to normal attributes and other
languages(*)? I see a lot of arguments for doing that, with the only
counter-argument that they would be in the same namespace as the
built-in attributes (which should not be that bad, as this is very low
level language stuff).

(*) i.e. @mytype or @(string) and without the '[]'


Re: User Defined Attributes

2012-11-06 Thread Walter Bright

On 11/6/2012 12:15 AM, Tove wrote:
 [*drool*, totally perfect awesomeness] Thanks!


The neato thing is I realized I could just connect the dots on what D already 
does well - CTFE, tuples, and templates. The actual features can now be added by 
library routines.


Re: User Defined Attributes

2012-11-06 Thread Walter Bright
On 11/6/2012 12:20 AM, Sönke Ludwig wrote: But shouldn't we keep the syntax 
closer to normal attributes and other

 languages(*)? I see a lot of arguments for doing that, with the only
 counter-argument that they would be in the same namespace as the
 built-in attributes (which should not be that bad, as this is very low
 level language stuff).

 (*) i.e. @mytype or @(string) and without the '[]'


We can debate the syntax. I don't have a store set by this one. I was more 
interested in getting the semantics right. Anyhow, it's nice to have a working 
prototype to experiment with rather than a paper airplane.


Re: User Defined Attributes

2012-11-06 Thread Walter Bright
On 11/6/2012 12:39 AM, Jakob Ovrum wrote: On Tuesday, 6 November 2012 at 
07:55:51 UTC, Walter Bright wrote:

 -snip-

 It doesn't look like it would be possible to schedule any runtime code using
 this, meaning they're not usable for stuff like registering types for
 serialization support, or doing runtime linking when attached to a function
 pointer, etc.

Since D allows one to inquire and get a list of symbols, one can then iterate 
over them at compile time to determine which are serializable (or have some 
other specific attribute).




Re: User Defined Attributes

2012-11-06 Thread Jakob Ovrum

On Tuesday, 6 November 2012 at 08:42:44 UTC, Walter Bright wrote:
Since D allows one to inquire and get a list of symbols, one 
can then iterate over them at compile time to determine which 
are serializable (or have some other specific attribute).


Yes, but somewhere you have to put startup code pointing in the 
general direction of where the attributes are used (like a 
module), it's not automatic. A static constructor cannot be used 
because it has no idea where to look.


But, I yield until someone comes up with actual examples of how 
these UDAs are useful, because I can't think of anything 
interesting at the moment. I guess I should go read over the old 
discussions you linked (I remember participating, but can't 
remember any specifics).





Re: User Defined Attributes

2012-11-06 Thread Maxim Fomin

On Tuesday, 6 November 2012 at 07:55:51 UTC, Walter Bright wrote:

snip


Nice to hear because it was unexpected and was requested 
prevously by community.


Re: User Defined Attributes

2012-11-06 Thread Walter Bright

On 11/6/2012 12:42 AM, Walter Bright wrote:

Since D allows one to inquire and get a list of symbols, one can then iterate
over them at compile time to determine which are serializable (or have some
other specific attribute).



To emphasize, the User Defined Attributes thing is completely a compile time 
feature. However, a user defined runtime system can be built on top of it.


It gives the best of both worlds.



Re: User Defined Attributes

2012-11-06 Thread Sönke Ludwig
Am 06.11.2012 09:26, schrieb Walter Bright:
 On 11/6/2012 12:20 AM, Sönke Ludwig wrote: But shouldn't we keep the
 syntax closer to normal attributes and other
 languages(*)? I see a lot of arguments for doing that, with the only
 counter-argument that they would be in the same namespace as the
 built-in attributes (which should not be that bad, as this is very low
 level language stuff).

 (*) i.e. @mytype or @(string) and without the '[]'
 
 
 We can debate the syntax. I don't have a store set by this one. I was
 more interested in getting the semantics right. Anyhow, it's nice to
 have a working prototype to experiment with rather than a paper airplane.

Definitely! Thanks a lot for tackling this, to me this seems like
something that can get a real killer feature for the language!


Re: User Defined Attributes

2012-11-06 Thread Maxim Fomin

On Tuesday, 6 November 2012 at 08:39:47 UTC, Jakob Ovrum wrote:
On Tuesday, 6 November 2012 at 07:55:51 UTC, Walter Bright 
wrote:

-snip-


It doesn't look like it would be possible to schedule any 
runtime code using this, meaning they're not usable for stuff 
like registering types for serialization support, or doing 
runtime linking when attached to a function pointer, etc.




Runtime arrtibutes can be implemented as properties in object.d. 
This would work for classes only and for other types it can be 
implemented manually. Runtime attributes require substantial 
amount of work, introducing bugs, bloating ABI and new questions 
about how this feature does work with others.


Re: User Defined Attributes

2012-11-06 Thread Jakob Ovrum

On Tuesday, 6 November 2012 at 08:50:32 UTC, Walter Bright wrote:
To emphasize, the User Defined Attributes thing is completely a 
compile time feature. However, a user defined runtime system 
can be built on top of it.


It gives the best of both worlds.


Problem is that there's no way to do this without having the user 
specify which modules it should work for, like:


import attributes;
import a, b, c;

static this() // This code cannot be automated.
{
initAttributes!a();
initAttributes!b();
initAttributes!c();
}



Re: User Defined Attributes

2012-11-06 Thread dennis luehring

Am 06.11.2012 09:49, schrieb Jakob Ovrum:


But, I yield until someone comes up with actual examples of how
these UDAs are useful, because I can't think of anything
interesting at the moment. I guess I should go read over the old
discussions you linked (I remember participating, but can't
remember any specifics).


you're just to deep catched in the 
.Net-Everything-Is-Done-In-Runtime-Paradigm - thats all :)


most of the stuff .Net does in runtime is not absolutely needed at 
runtime - but they need to because there is no compiletime reflection 
system available at all - and that trains developer to always thing in 
runtime-aspects - always




Re: User Defined Attributes

2012-11-06 Thread Jakob Ovrum

On Tuesday, 6 November 2012 at 08:56:26 UTC, Maxim Fomin wrote:
Runtime arrtibutes can be implemented as properties in 
object.d. This would work for classes only and for other types 
it can be implemented manually. Runtime attributes require 
substantial amount of work, introducing bugs, bloating ABI and 
new questions about how this feature does work with others.


I'm not suggesting runtime attributes should be part of the 
language, nor am I suggesting we add them to Phobos.


All I'm saying is the UDA system has to be powerful enough that 
it *could* be implemented in a library if desired.




Re: User Defined Attributes

2012-11-06 Thread alex

On Tuesday, 6 November 2012 at 08:55:06 UTC, Sönke Ludwig wrote:

Am 06.11.2012 09:26, schrieb Walter Bright:
On 11/6/2012 12:20 AM, Sönke Ludwig wrote: But shouldn't we 
keep the

syntax closer to normal attributes and other
languages(*)? I see a lot of arguments for doing that, with 
the only
counter-argument that they would be in the same namespace as 
the
built-in attributes (which should not be that bad, as this is 
very low

level language stuff).

(*) i.e. @mytype or @(string) and without the '[]'



We can debate the syntax. I don't have a store set by this 
one. I was
more interested in getting the semantics right. Anyhow, it's 
nice to
have a working prototype to experiment with rather than a 
paper airplane.


Definitely! Thanks a lot for tackling this, to me this seems 
like

something that can get a real killer feature for the language!


@test
void myUnittest()
{

}

Uh yeah, that would be awesome!


Re: User Defined Attributes

2012-11-06 Thread Jakob Ovrum
On Tuesday, 6 November 2012 at 09:03:49 UTC, dennis luehring 
wrote:
you're just to deep catched in the 
.Net-Everything-Is-Done-In-Runtime-Paradigm - thats all :)


No.


Re: User Defined Attributes

2012-11-06 Thread Walter Bright

n 11/6/2012 12:59 AM, Jakob Ovrum wrote:
 Problem is that there's no way to do this without having the user specify 
which
 modules it should work for, like:

 import attributes;
 import a, b, c;

 static this() // This code cannot be automated.
 {
  initAttributes!a();
  initAttributes!b();
  initAttributes!c();
 }


Is that really a problem?


Re: User Defined Attributes

2012-11-06 Thread Walter Bright

On 11/6/2012 12:49 AM, Maxim Fomin wrote:

On Tuesday, 6 November 2012 at 07:55:51 UTC, Walter Bright wrote:

snip


Nice to hear because it was unexpected and was requested prevously by community.


I've been intending to do it for a while now.


Re: User Defined Attributes

2012-11-06 Thread dennis luehring

Am 06.11.2012 10:04, schrieb Jakob Ovrum:

On Tuesday, 6 November 2012 at 09:03:49 UTC, dennis luehring
wrote:

you're just to deep catched in the
.Net-Everything-Is-Done-In-Runtime-Paradigm - thats all :)


No.


ok not you - but many others



Re: User Defined Attributes

2012-11-06 Thread Walter Bright

On 11/6/2012 1:06 AM, Jonas Drewsen wrote:

Wow! This is an early christmas gift.

Just to be sure. Is the following also possible:

[Serializable]
class Foo
{
int bar;
}

This will attach the UDA to the ClassDeclaration.

The examples you've shown only attach UDAs to variable declarations.

/Jonas



Yes, you can attach them to other symbols, including user defined types.


Re: User Defined Attributes

2012-11-06 Thread Jonas Drewsen

Wow! This is an early christmas gift.

Just to be sure. Is the following also possible:

[Serializable]
class Foo
{
   int bar;
}

This will attach the UDA to the ClassDeclaration.

The examples you've shown only attach UDAs to variable 
declarations.


/Jonas



Re: User Defined Attributes

2012-11-06 Thread Jonas Drewsen

On Tuesday, 6 November 2012 at 09:08:25 UTC, Walter Bright wrote:

On 11/6/2012 1:06 AM, Jonas Drewsen wrote:

Wow! This is an early christmas gift.

Just to be sure. Is the following also possible:

[Serializable]
class Foo
{
   int bar;
}

This will attach the UDA to the ClassDeclaration.

The examples you've shown only attach UDAs to variable 
declarations.


/Jonas



Yes, you can attach them to other symbols, including user 
defined types.


Great. Can't wait to play around with this. I think project 
Orange could really take advantage of this.


/Jonas



Re: User Defined Attributes

2012-11-06 Thread Jens Mueller
Walter Bright wrote:
 References:
 
 http://www.digitalmars.com/d/archives/digitalmars/D/Custom_attributes_again_163042.html
 
 http://www.digitalmars.com/d/archives/digitalmars/D/custom_attribute_proposal_yeah_another_one_163246.html
 
 Inspired by a gallon of coffee, I decided to get it implemented.
 It's simple, based on what D already does (CTFE and heterogeneous
 tuples), easy to implement, easy to understand, and doesn't break
 anything. It should do everything asked for in the above references
 (except it's not a type constructor).
 
 You can download it here and try it out:
 
 http://ftp.digitalmars.com/dmd2beta.zip
 
 As a bonus, that beta also can generate Win64 executables, and you
 can even symbolically debug them with VS! (Thanks to Rainer Schütze
 for his invaluable help with that).
 
 Here's the rather skimpy and lame spec I banged out:
 =
 User Defined Attributes
 ---
 
 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.
 
 Grammatically, a UDA is a StorageClass:
 
 StorageClass:
   UserDefinedAttribute
 
 UserDefinedAttribute:
 [ ArgumentList ]
 
 And looks like:
 
 [ 3 ] int a;
 [ string, 7 ]: int b;
 
 If there are multiple UDAs in scope for a declaration, they are concatenated:
 
 [ 1 ] {
[ 2 ] int a;// has UDA's [1,2]
[ string ] int b; // has UDA's [1,string]
 }
 
 UDA's can be extracted into an expression tuple using __traits:
 
 [ 'c' ] string s;
 pragma(msg, __traits(getAttributes, s));
 
 prints:
 
 tuple('c')
 
 If there are no user defined attributes for the symbol, an empty tuple is 
 returned.
 The expression tuple can be turned into a manipulatable tuple:
 
   template Tuple(T...) {
 alias T Tuple;
   }
 
   enum EEE = 7;
   [hello] struct SSS { }
   [3] { [4][EEE][SSS] int foo; }
 
   alias Tuple!(__traits(getAttributes, foo)) TP;
 
   pragma(msg, TP);
   pragma(msg, TP[2]);
 
 prints:
 
   tuple(3,4,7,(SSS))
   7
 
 and of course the tuple types can be used to declare things:
 
   TP[3] a;// a is declared as an SSS
 
 The attribute of the type name is not the same as the attribute of the 
 variable:
 
   pragma(msg, __traits(getAttributes, typeof(a));
 
 prints:
 
 tuple(hello)
 
 Of course, the real value of UDA's is to be able to create user defined types 
 with
 specific values. Having attribute values of basic types does not scale.
 The attribute tuples can be manipulated like any other tuple, and
 can be passed as the argument list to a template.
 
 Whether the attributes are values or types is up to the user, and whether 
 later
 attributes accumulate or override earlier ones is also up to how the
 user interprets them.

I wonder what are the benefits over a library solution. Something like

struct UserDefinedAttribute(Args...)
{
alias Args[0 .. $ -1] attributes;
}

unittest
{
UserDefinedAttribute!(my attr, int) a;
UserDefinedAttribute!(my attr, 4, int) b;

import std.stdio;
writeln(typeof(a).attributes.stringof);
writeln(typeof(b).attributes.stringof);
}

which admittedly has less syntactical appeal (and probably other
problems) but can maybe improved. But to which point.
What do you gain by adding it to the core language?

Jens


Re: User Defined Attributes

2012-11-06 Thread Sönke Ludwig
Am 06.11.2012 09:39, schrieb Jakob Ovrum:
 On Tuesday, 6 November 2012 at 07:55:51 UTC, Walter Bright wrote:
 -snip-
 
 It doesn't look like it would be possible to schedule any runtime code
 using this, meaning they're not usable for stuff like registering types
 for serialization support, or doing runtime linking when attached to a
 function pointer, etc.
 
 Even with user defined types or functions used in the attribute, the
 type or function itself doesn't know anything about the symbol it is
 being attached to, so it's quite limited what it can do.
 
 Compared to other prevalent UDA systems, like C#'s, I'd say that this
 one is extremely limiting due to the two above points.
 
 I'd love to hear some examples of what this particular take on UDAs
 allows in D, though.
 

I see this as a feature in a way. The way C# attributes are sometimes
used can feel a lot like magic, because they can do things on their own.
In contrast it feels quite clean to me to simply think of attributes of
what the word means - a simple tag on the declaration.

Some otherwise possible globally operating applications may not be
doable without some boilerplate code. But a lot of stuff, including
controlling seralization, interface generation or statically checked
custom type constraints should be perfectly possible.


Re: User Defined Attributes

2012-11-06 Thread Jens Mueller
Jens Mueller wrote:
 Walter Bright wrote:
  References:
  
  http://www.digitalmars.com/d/archives/digitalmars/D/Custom_attributes_again_163042.html
  
  http://www.digitalmars.com/d/archives/digitalmars/D/custom_attribute_proposal_yeah_another_one_163246.html
  
  Inspired by a gallon of coffee, I decided to get it implemented.
  It's simple, based on what D already does (CTFE and heterogeneous
  tuples), easy to implement, easy to understand, and doesn't break
  anything. It should do everything asked for in the above references
  (except it's not a type constructor).
  
  You can download it here and try it out:
  
  http://ftp.digitalmars.com/dmd2beta.zip
  
  As a bonus, that beta also can generate Win64 executables, and you
  can even symbolically debug them with VS! (Thanks to Rainer Schütze
  for his invaluable help with that).
  
  Here's the rather skimpy and lame spec I banged out:
  =
  User Defined Attributes
  ---
  
  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.
  
  Grammatically, a UDA is a StorageClass:
  
  StorageClass:
  UserDefinedAttribute
  
  UserDefinedAttribute:
  [ ArgumentList ]
  
  And looks like:
  
  [ 3 ] int a;
  [ string, 7 ]: int b;
  
  If there are multiple UDAs in scope for a declaration, they are 
  concatenated:
  
  [ 1 ] {
 [ 2 ] int a;// has UDA's [1,2]
 [ string ] int b; // has UDA's [1,string]
  }
  
  UDA's can be extracted into an expression tuple using __traits:
  
  [ 'c' ] string s;
  pragma(msg, __traits(getAttributes, s));
  
  prints:
  
  tuple('c')
  
  If there are no user defined attributes for the symbol, an empty tuple is 
  returned.
  The expression tuple can be turned into a manipulatable tuple:
  
template Tuple(T...) {
  alias T Tuple;
}
  
enum EEE = 7;
[hello] struct SSS { }
[3] { [4][EEE][SSS] int foo; }
  
alias Tuple!(__traits(getAttributes, foo)) TP;
  
pragma(msg, TP);
pragma(msg, TP[2]);
  
  prints:
  
tuple(3,4,7,(SSS))
7
  
  and of course the tuple types can be used to declare things:
  
TP[3] a;// a is declared as an SSS
  
  The attribute of the type name is not the same as the attribute of the 
  variable:
  
pragma(msg, __traits(getAttributes, typeof(a));
  
  prints:
  
  tuple(hello)
  
  Of course, the real value of UDA's is to be able to create user defined 
  types with
  specific values. Having attribute values of basic types does not scale.
  The attribute tuples can be manipulated like any other tuple, and
  can be passed as the argument list to a template.
  
  Whether the attributes are values or types is up to the user, and whether 
  later
  attributes accumulate or override earlier ones is also up to how the
  user interprets them.
 
 I wonder what are the benefits over a library solution. Something like
 
 struct UserDefinedAttribute(Args...)
 {
   alias Args[0 .. $ -1] attributes;
 }
 
 unittest
 {
   UserDefinedAttribute!(my attr, int) a;
   UserDefinedAttribute!(my attr, 4, int) b;
 
   import std.stdio;
   writeln(typeof(a).attributes.stringof);
   writeln(typeof(b).attributes.stringof);
 }
 
 which admittedly has less syntactical appeal (and probably other
 problems) but can maybe improved. But to which point.
 What do you gain by adding it to the core language?

No need to reply.
Since you said already
Yes, you can attach them to other symbols, including user defined types.
That wasn't obvious from the examples. That's why it looked initially
limited to me.

Jens


Re: User Defined Attributes

2012-11-06 Thread Tove

Tooo much fun! Argh, _must_ _stop_ _playing_ and actually work ;(

[int a;]
class A
{
}

class B : A
{
  mixin(__traits(getAttributes, typeof(super))[0]);
}

can't wait to see all the creative uses this will enable!



Re: User Defined Attributes

2012-11-06 Thread simendsjo

On Tuesday, 6 November 2012 at 10:10:37 UTC, Tove wrote:
Tooo much fun! Argh, _must_ _stop_ _playing_ and actually work 
;(


[int a;]
class A
{
}

class B : A
{
  mixin(__traits(getAttributes, typeof(super))[0]);
}

can't wait to see all the creative uses this will enable!


Or obfuscation :)


Re: User Defined Attributes

2012-11-06 Thread Jakob Ovrum

On Tuesday, 6 November 2012 at 09:24:58 UTC, Jens Mueller wrote:

which admittedly has less syntactical appeal (and probably other
problems) but can maybe improved. But to which point.
What do you gain by adding it to the core language?

Jens


In the initial discussions, I was hoping that the symbol itself 
would be made available in some fashion. For example, enabling 
something like this:


template Test(alias sym)
{
pragma(msg, test attribute was attached to:);
pragma(msg, sym);
enum Test = true;
}

[Test] int a;

However, I can imagine that it's always possible to work around 
this by doing the actual work later when both the symbol and 
attribute are available.




Re: User Defined Attributes

2012-11-06 Thread Jakob Ovrum

On Tuesday, 6 November 2012 at 09:07:34 UTC, Walter Bright wrote:

Is that really a problem?


I don't strictly need it for any of my projects, where I'm 
already using lazy initialization for these cases. I guess time 
will tell if it's significant for other applications.




Re: User Defined Attributes

2012-11-06 Thread Max Samukha

On Tuesday, 6 November 2012 at 08:20:42 UTC, Walter Bright wrote:

On 11/6/2012 12:15 AM, Tove wrote:
 [*drool*, totally perfect awesomeness] Thanks!


The neato thing is I realized I could just connect the dots on 
what D already does well - CTFE, tuples, and templates. The 
actual features can now be added by library routines.


Thank you. Now we can stop connecting the dots with hidden
declaration hacks. Yay!



Re: User Defined Attributes

2012-11-06 Thread Max Samukha

On Tuesday, 6 November 2012 at 07:55:51 UTC, Walter Bright wrote:


=
User Defined Attributes
---



Attributes on overloads are critical. Currently fails:

module test;

[1] void foo();
[2] void foo(int x);

template Tuple(A...)
{
alias A Tuple;
}

void main()
{
foreach (o; __traits(getOverloads, test, foo))
{
alias Tuple!(__traits(getAttributes, o)) attrs;
pragma(msg, attrs.stringof);
}
}

Compiler outputs:
()
()



Re: User Defined Attributes

2012-11-06 Thread angel

How do the attributes interact with inheritance ?
What happens when one inherits an attribute-decorated class ?
I can picture both situations, when you would like to see the 
attributes inherited, and when you would prefer them dropped.




Re: User Defined Attributes

2012-11-06 Thread Jacob Carlborg

On 2012-11-06 09:20, Sönke Ludwig wrote:

Wow, that's a surprise! Just yesterday I was thinking that it would be
really nice to have them for a piece of code ;)

But shouldn't we keep the syntax closer to normal attributes and other
languages(*)? I see a lot of arguments for doing that, with the only
counter-argument that they would be in the same namespace as the
built-in attributes (which should not be that bad, as this is very low
level language stuff).

(*) i.e. @mytype or @(string) and without the '[]'


I agree, I a syntax like this would have been nicer:

@mtype(key : value) int a; or @mtype(key : value) int a;
@mtype(value) int b;
@mtype int c;

--
/Jacob Carlborg


Re: User Defined Attributes

2012-11-06 Thread Adam D. Ruppe

On Tuesday, 6 November 2012 at 07:55:51 UTC, Walter Bright wrote:
User Defined Attributes (UDA) are compile time expressions that 
can be attached to a declaration.


Hmmm, it didn't work on the most important place for my use case, 
function parameters:


void a([test] int foo) {
pragma(msg, __traits(getAttributes, foo));
}

test.d(1): Error: basic type expected, not [
test.d(1): Error: found 'int' when expecting ')'
test.d(1): Error: semicolon expected following function 
declaration

test.d(1): Error: no identifier for declarator foo
test.d(1): Error: semicolon expected, not ')'
test.d(1): Error: Declaration expected, not ')'



The reason why this is important to me is I have a nice automatic 
form builder given a function signature. I'd like to add things 
like hints about the params that my existing code can take a look 
at.



(a problem that might remain is being able to reference the 
parameters outside... I use a ParameterTypeTuple and .stringof 
right now but that probably won't work for getAttributes. But we 
can always solve that later.)


Re: User Defined Attributes

2012-11-06 Thread Adam D. Ruppe

On Tuesday, 6 November 2012 at 13:08:15 UTC, Jacob Carlborg wrote:

Also have a more key-value like mapping, something like this:


We can always use custom types to get this kind of thing.

struct key { string value; }

[key(value)] foo


Re: User Defined Attributes

2012-11-06 Thread nazriel

On Tuesday, 6 November 2012 at 07:55:51 UTC, Walter Bright wrote:

References:

http://www.digitalmars.com/d/archives/digitalmars/D/Custom_attributes_again_163042.html

http://www.digitalmars.com/d/archives/digitalmars/D/custom_attribute_proposal_yeah_another_one_163246.html



I tried to build DMD git for dpaste, so people can play with UDA 
but DMD segfaults when building Phobos


Program received signal SIGSEGV, Segmentation fault.
0x00403179 in ClassDeclaration::getAccess(Dsymbol*) ()
(gdb) bt
#0  0x00403179 in ClassDeclaration::getAccess(Dsymbol*) ()
#1  0x00403614 in AggregateDeclaration::accessCheck(Loc, 
Scope*, Dsymbol*) ()

#2  0x00459f36 in CallExp::semantic(Scope*) ()
#3  0x004ccceb in ExpStatement::semantic(Scope*) ()
#4  0x004d0cdd in CompoundStatement::semantic(Scope*) ()
#5  0x0046b830 in FuncDeclaration::semantic3(Scope*) ()
#6  0x00448418 in FuncExp::semantic(Scope*) ()
#7  0x004a0a0a in TypeTypeof::semantic(Loc, Scope*) ()
#8  0x00499b61 in Type::trySemantic(Loc, Scope*) ()
#9  0x0044e16e in IsExp::semantic(Scope*) ()
#10 0x00427e4a in StaticIfCondition::include(Scope*, 
ScopeDsymbol*) ()
#11 0x004058e2 in ConditionalDeclaration::include(Scope*, 
ScopeDsymbol*) ()
#12 0x00405987 in StaticIfDeclaration::include(Scope*, 
ScopeDsymbol*) ()
#13 0x00403fe0 in AttribDeclaration::addMember(Scope*, 
ScopeDsymbol*, int) ()
#14 0x00405add in StaticIfDeclaration::addMember(Scope*, 
ScopeDsymbol*, int) ()
#15 0x00404015 in AttribDeclaration::addMember(Scope*, 
ScopeDsymbol*, int) ()



Well, anyways, I fetched package prepared in first post.
So folks, you can play with UDA on http://dpaste.dzfl.pl - by 
picking DMD2 git - without messing with DMD packages in your OS :)


http://dpaste.dzfl.pl/9c2e8b20

Also if I declare string with UDA inside main() I get error:
http://dpaste.dzfl.pl/909a34c8


Re: User Defined Attributes

2012-11-06 Thread Rory McGuire
You can put the attribute on the function.
There are a couple of go libraries that use struct tags in a similar way.
Such as code.google.com/p/gorest
 On 6 Nov 2012 15:15, Adam D. Ruppe destructiona...@gmail.com wrote:

 On Tuesday, 6 November 2012 at 07:55:51 UTC, Walter Bright wrote:

 User Defined Attributes (UDA) are compile time expressions that can be
 attached to a declaration.


 Hmmm, it didn't work on the most important place for my use case, function
 parameters:

 void a([test] int foo) {
 pragma(msg, __traits(getAttributes, foo));
 }

 test.d(1): Error: basic type expected, not [
 test.d(1): Error: found 'int' when expecting ')'
 test.d(1): Error: semicolon expected following function declaration
 test.d(1): Error: no identifier for declarator foo
 test.d(1): Error: semicolon expected, not ')'
 test.d(1): Error: Declaration expected, not ')'



 The reason why this is important to me is I have a nice automatic form
 builder given a function signature. I'd like to add things like hints about
 the params that my existing code can take a look at.


 (a problem that might remain is being able to reference the parameters
 outside... I use a ParameterTypeTuple and .stringof right now but that
 probably won't work for getAttributes. But we can always solve that later.)



Re: User Defined Attributes

2012-11-06 Thread Jacob Carlborg

On 2012-11-06 14:17, Adam D. Ruppe wrote:


We can always use custom types to get this kind of thing.

struct key { string value; }

[key(value)] foo


Right, good point. But I would still like to somehow be able to name an 
attribute. If one just need to mark a symbol, i.e.


@test void foo () {}

Then one either have to use a string literal or something like a dummy 
variable/type.


[test] void foo () {}

enum test = test;

[test] void foo () {}

Or

struct test {}

[test()] void foo () {}

--
/Jacob Carlborg


Re: User Defined Attributes

2012-11-06 Thread Adam D. Ruppe

On Tuesday, 6 November 2012 at 13:55:49 UTC, Rory McGuire wrote:

You can put the attribute on the function.


Yeah, but that's an awfully roundabout way to add an attribute to 
the parameter...


if it went on func params:
void foo([Hint(this does something)] string something) {}

otherwise we'd have to do something like

[ParamHint(something, this does something)] void foo(string 
something) {}



Which isn't really ahead from the old hack of

enum attr_foo_someting = Hint();

and has similar problems in matching names. It's a little better 
but not as good as it could be.


Re: User Defined Attributes

2012-11-06 Thread Gor Gyolchanyan

On Tuesday, 6 November 2012 at 14:05:46 UTC, Adam D. Ruppe wrote:

On Tuesday, 6 November 2012 at 13:55:49 UTC, Rory McGuire wrote:

You can put the attribute on the function.


Yeah, but that's an awfully roundabout way to add an attribute 
to the parameter...


if it went on func params:
void foo([Hint(this does something)] string something) {}

otherwise we'd have to do something like

[ParamHint(something, this does something)] void foo(string 
something) {}



Which isn't really ahead from the old hack of

enum attr_foo_someting = Hint();

and has similar problems in matching names. It's a little 
better but not as good as it could be.


What if the data in the attribute needs to be specific to the 
symbol on which the attribute is set on? Can you query the symbol 
from inside the attribute?

What if the attribute needs to change the symbol being defined?
For instance (using commonly desired syntax):

@flags enum A { ... }

the flags attribute would replace the declaraction of A with 
another enum declaration with the same name and same members, but 
with replaced initialization and would static assert(false, 
flags enum can't have initializers) if any initializers are 
given.


The existing [data] declaration is one thing. It adds 
compile-time data to symbols, which is very very important, but 
it's not the only thing that is needed. What I described above is 
not quite an attribute, but an annotation. The semantics of 
attributes as Walter made them is perfect. The annotation should 
be  defined like so:


template myAnnotation(alias symbol, annot_args...)
{
// ...
[myAnnoration adds this attribute] alias symbol 
myAnnotation; // or alias anything else if a change in necessary.

}

@myAnnotation(arg1, arg2, arg3) class Declaration
{
}

here the symbol is passed to the template as the first 
parameter and the parameters in the parentheses are passes after 
it. It's basically a thin syntactic sugar over some manual (and 
very ugly) manual template instantiations (and mixins), so it 
doesn't add anything new.


Annotations then become a way to statically replace declarations.
This would be perfect to replace

Scoped!MyClass mc;

with:

@scoped MyClass mc;

Which looks quite like a very beautiful built-in syntax, but is 
actually a library solution.


IMHO, Attributes as they are should stay, but annotations should 
be added.


P.S. Thank you, Walter very very much for making attributes!!! :-)


Re: User Defined Attributes

2012-11-06 Thread Jacob Carlborg

On 2012-11-06 15:23, Gor Gyolchanyan wrote:


What if the data in the attribute needs to be specific to the symbol on
which the attribute is set on? Can you query the symbol from inside the
attribute?
What if the attribute needs to change the symbol being defined?
For instance (using commonly desired syntax):

@flags enum A { ... }

the flags attribute would replace the declaraction of A with another
enum declaration with the same name and same members, but with replaced
initialization and would static assert(false, flags enum can't have
initializers) if any initializers are given.

The existing [data] declaration is one thing. It adds compile-time
data to symbols, which is very very important, but it's not the only
thing that is needed. What I described above is not quite an attribute,
but an annotation. The semantics of attributes as Walter made them is
perfect. The annotation should be  defined like so:

template myAnnotation(alias symbol, annot_args...)
{
 // ...
 [myAnnoration adds this attribute] alias symbol myAnnotation; //
or alias anything else if a change in necessary.
}

@myAnnotation(arg1, arg2, arg3) class Declaration
{
}

here the symbol is passed to the template as the first parameter and
the parameters in the parentheses are passes after it. It's basically a
thin syntactic sugar over some manual (and very ugly) manual template
instantiations (and mixins), so it doesn't add anything new.

Annotations then become a way to statically replace declarations.
This would be perfect to replace

Scoped!MyClass mc;

with:

@scoped MyClass mc;

Which looks quite like a very beautiful built-in syntax, but is actually
a library solution.

IMHO, Attributes as they are should stay, but annotations should be added.

P.S. Thank you, Walter very very much for making attributes!!! :-)


I like this proposal as well.

--
/Jacob Carlborg


Re: User Defined Attributes

2012-11-06 Thread dennis luehring

Am 06.11.2012 14:14, schrieb Adam D. Ruppe:

On Tuesday, 6 November 2012 at 07:55:51 UTC, Walter Bright wrote:

User Defined Attributes (UDA) are compile time expressions that
can be attached to a declaration.


Hmmm, it didn't work on the most important place for my use case,
function parameters:

void a([test] int foo) {
  pragma(msg, __traits(getAttributes, foo));
}


sad - but its still very young feature :)

im using something like an description on my methods to describe 
parameter features for an resource manager - something like read, 
write, copy, read_write etc.


to have this at compiletime available by using UDAs on parameters  + an 
compiletime generator would be absolutely briliant


my vote +1 for UDAs on parameters



Re: User Defined Attributes

2012-11-06 Thread Walter Bright

On 11/6/2012 4:18 AM, Max Samukha wrote:

Attributes on overloads are critical. Currently fails:


That should work. Will investigate.



Re: User Defined Attributes

2012-11-06 Thread Tove

On Tuesday, 6 November 2012 at 13:14:50 UTC, Adam D. Ruppe wrote:
On Tuesday, 6 November 2012 at 07:55:51 UTC, Walter Bright 
wrote:
User Defined Attributes (UDA) are compile time expressions 
that can be attached to a declaration.


Hmmm, it didn't work on the most important place for my use 
case, function parameters:


void a([test] int foo) {
pragma(msg, __traits(getAttributes, foo));
}



Hmmm, actually it doesn't work in plain function/block scope 
either.


void a()
{
  [test] int foo;
  pragma(msg, __traits(getAttributes, foo));
}
Error: found 'int' when expecting ';' following statement



Re: User Defined Attributes

2012-11-06 Thread Walter Bright

On 11/6/2012 4:24 AM, angel wrote:
 How do the attributes interact with inheritance ?
 What happens when one inherits an attribute-decorated class ?


The attributes are for the symbol, not the type.


Re: User Defined Attributes

2012-11-06 Thread Walter Bright

On 11/6/2012 6:30 AM, dennis luehring wrote:
 Am 06.11.2012 14:14, schrieb Adam D. Ruppe:
 On Tuesday, 6 November 2012 at 07:55:51 UTC, Walter Bright wrote:
 User Defined Attributes (UDA) are compile time expressions that
 can be attached to a declaration.

 Hmmm, it didn't work on the most important place for my use case,
 function parameters:

 void a([test] int foo) {
   pragma(msg, __traits(getAttributes, foo));
 }

 sad - but its still very young feature :)

 im using something like an description on my methods to describe parameter
 features for an resource manager - something like read, write, copy,
 read_write etc.

But there's already out=write, read=all of them, read_write=ref, copy=not a ref 
or an out.


I don't know what use UDAs would be for parameters.



Re: User Defined Attributes

2012-11-06 Thread Walter Bright

On 11/6/2012 5:14 AM, Adam D. Ruppe wrote:

Hmmm, it didn't work on the most important place for my use case, function
parameters:


It didn't occur to me to enable that.



Re: User Defined Attributes

2012-11-06 Thread Walter Bright

On 11/6/2012 5:57 AM, Jacob Carlborg wrote:

But I would still like to somehow be able to name an
attribute. If one just need to mark a symbol, i.e.

@test void foo () {}

Then one either have to use a string literal or something like a dummy
variable/type.

[test] void foo () {}


Which does exactly what you ask for.



enum test = test;

[test] void foo () {}


or:

   enum EEE;
   [EEE] void foo() { }



Re: User Defined Attributes

2012-11-06 Thread Walter Bright

On 11/6/2012 7:14 AM, Tove wrote:

Hmmm, actually it doesn't work in plain function/block scope either.


Right, I don't see a compelling purpose for that, either.



Re: User Defined Attributes

2012-11-06 Thread Adam D. Ruppe

On Tuesday, 6 November 2012 at 15:18:55 UTC, Walter Bright wrote:

I don't know what use UDAs would be for parameters.


It's pretty much the same as anywhere else: to add useful data 
for reflection. A few I'd use it for is providing user visible 
data like label and hint for automatic UI generation, or styling 
hints again for the auto ui (e.g. use a multi-line input for 
this string).


We could also potentially put validation in there, though this 
may be on the type as well. Or put on info to check for 
availability of a username.



If you do an automatic UI generator, attributes on the parameters 
have a lot of uses. Other than that, well, I don't know, but 
that's probably just because I haven't done it yet!


Re: User Defined Attributes

2012-11-06 Thread Jacob Carlborg

On 2012-11-06 16:15, Walter Bright wrote:


enum test = test;

[test] void foo () {}


or:

enum EEE;
[EEE] void foo() { }



First, I didn't know you could have an empty enum. Second, that was my 
point. I don't like the need for a dummy/empty enum, or the use of a 
string literal.


--
/Jacob Carlborg


Re: User Defined Attributes

2012-11-06 Thread Walter Bright

On 11/6/2012 5:04 AM, Jacob Carlborg wrote:

I agree, I a syntax like this would have been nicer:

@mtype(key : value) int a; or @mtype(key : value) int a;
@mtype(value) int b;
@mtype int c;



Part of what I was trying to do was minimizing inventing new syntaxes. The

   [ ArgumentList ]

invents nothing new but the brackets. Your proposal is both a new syntax, and it 
can only do key/value pairs - nothing else.


Re: User Defined Attributes

2012-11-06 Thread Jacob Carlborg

On 2012-11-06 16:39, Walter Bright wrote:

On 11/6/2012 5:04 AM, Jacob Carlborg wrote:

I agree, I a syntax like this would have been nicer:

@mtype(key : value) int a; or @mtype(key : value) int a;
@mtype(value) int b;
@mtype int c;



Part of what I was trying to do was minimizing inventing new syntaxes. The

[ ArgumentList ]

invents nothing new but the brackets. Your proposal is both a new
syntax, and it can only do key/value pairs - nothing else.


It depends on how you look at it.

* @mtype - is the same syntax as the current syntax for attributes
* @mtype(key : value) - Uses the above in combination with the 
syntax for associative array literals


How about this then:

@mtype(foo, 3, bar) int a;

And have the argument list be optional? I really like to have a short 
nice looking syntax for the simple use cases, i.e.


@mtype int b;

--
/Jacob Carlborg


Re: User Defined Attributes

2012-11-06 Thread Jacob Carlborg

On 2012-11-06 16:42, Walter Bright wrote:


I see your point, but if such was implemented that way, then the UDAs
would be extremely limited, and there'd be all sorts of issues with name
scoping. Pretty much all that would have to not only be reinvented, but
reams of documentation would have to be crafted explaining how it is
different from normal names.


No, I don't think so, see one of my other replies:

http://forum.dlang.org/thread/k7afq6$2832$1...@digitalmars.com?page=6#post-k7bbsu:2411ls:241:40digitalmars.com

--
/Jacob Carlborg


Re: User Defined Attributes

2012-11-06 Thread Sönke Ludwig
Am 06.11.2012 16:55, schrieb Jacob Carlborg:
 On 2012-11-06 16:39, Walter Bright wrote:
 On 11/6/2012 5:04 AM, Jacob Carlborg wrote:
 I agree, I a syntax like this would have been nicer:

 @mtype(key : value) int a; or @mtype(key : value) int a;
 @mtype(value) int b;
 @mtype int c;


 Part of what I was trying to do was minimizing inventing new syntaxes.
 The

 [ ArgumentList ]

 invents nothing new but the brackets. Your proposal is both a new
 syntax, and it can only do key/value pairs - nothing else.
 
 It depends on how you look at it.
 
 * @mtype - is the same syntax as the current syntax for attributes
 * @mtype(key : value) - Uses the above in combination with the
 syntax for associative array literals
 
 How about this then:
 
 @mtype(foo, 3, bar) int a;
 
 And have the argument list be optional? I really like to have a short
 nice looking syntax for the simple use cases, i.e.
 
 @mtype int b;
 

+1

Also, if mtype is a template, it could naturally be @mtype!(1, 2, 3).
Without the '!' it would be a function that is evaluated at CT. And just
@mtype would yield an alias of mtype.


Re: User Defined Attributes

2012-11-06 Thread Walter Bright

On 11/6/2012 5:23 AM, nazriel wrote:

I tried to build DMD git for dpaste, so people can play with UDA but DMD
segfaults when building Phobos


The auto tester shows it's working.

http://d.puremagic.com/test-results/


Re: User Defined Attributes

2012-11-06 Thread Johannes Pfau
Am Tue, 06 Nov 2012 09:49:42 +0100
schrieb Jakob Ovrum jakobov...@gmail.com:

 But, I yield until someone comes up with actual examples of how 
 these UDAs are useful, because I can't think of anything 
 interesting at the moment. I guess I should go read over the old 
 discussions you linked (I remember participating, but can't 
 remember any specifics).
 
 

The std.benchmark proposal currently requires all benchmark functions to
be named benchmark_name:

void benchmark_stdio_write_test() {}

with UDA:

@benchmark(stdio write test) void benchStdioWrite();

Of course you still need that sheduleBenchmarks mixin in every module
and of course it'd be nice to avoid that. But UDAs are already a big
step forward.


Re: User Defined Attributes

2012-11-06 Thread Tove

On Tuesday, 6 November 2012 at 15:19:53 UTC, Walter Bright wrote:

On 11/6/2012 7:14 AM, Tove wrote:
Hmmm, actually it doesn't work in plain function/block scope 
either.


Right, I don't see a compelling purpose for that, either.


Hmm, what about library based GC annotations?

[GC.NoScan] int* local_p;



Re: User Defined Attributes

2012-11-06 Thread Walter Bright

On 11/6/2012 7:55 AM, Jacob Carlborg wrote:

On 2012-11-06 16:39, Walter Bright wrote:

On 11/6/2012 5:04 AM, Jacob Carlborg wrote:

I agree, I a syntax like this would have been nicer:

@mtype(key : value) int a; or @mtype(key : value) int a;
@mtype(value) int b;
@mtype int c;



Part of what I was trying to do was minimizing inventing new syntaxes. The

[ ArgumentList ]

invents nothing new but the brackets. Your proposal is both a new
syntax, and it can only do key/value pairs - nothing else.


It depends on how you look at it.

* @mtype - is the same syntax as the current syntax for attributes
* @mtype(key : value) - Uses the above in combination with the syntax for
associative array literals

How about this then:

@mtype(foo, 3, bar) int a;

And have the argument list be optional? I really like to have a short nice
looking syntax for the simple use cases, i.e.

@mtype int b;



There's a lot more you can do with the ArgumentList syntax than associative 
arrays. Furthermore, there remains the problem of how mtype fits into the name 
scoping system.


Re: User Defined Attributes

2012-11-06 Thread bearophile
For the syntax maybe it's better something like @() instead of 
[], so it becomes more greppable and more easy to tell apart 
visually from the array literals:


@(1, xx, Foo) int x;


Supporting annotations for function arguments is probably an 
important sub-feature.


Yesterday I was discussing about the bug-prone nature of foreach 
loops on a struct array, and one of the solutions I've suggested 
was a user-defined annotation for the programmer to denote that 
she wants to modify just the copy:


struct Foo {}
Foo[10] foos;
foreach (@copy f; foos) { ... }

With UDA syntax:

foreach ([Copy] f; foos) { ... }
Or:
foreach (@(Copy) f; foos) { ... }

But I think there's no way to tell the compiler to give a 
compile-time error if such annotation is not present there 
(unless there's ref).


-

Gor Gyolchanyan:


@flags enum A { ... }

the flags attribute would replace the declaraction of A with 
another enum declaration with the same name and same members, 
but with replaced initialization and would static assert(false, 
flags enum can't have initializers) if any initializers are 
given.


I appreciate your idea (I think of user-defined attributes also 
as ways to extend the type system), But I know the engineer in 
Walter prefers extra-simple ideas, so maybe your idea will not be 
accepted :-) But let's see.


Bye,
bearophile


Re: User Defined Attributes

2012-11-06 Thread Walter Bright
On 11/6/2012 8:04 AM, Johannes Pfau wrote: The std.benchmark proposal currently 
requires all benchmark functions to

 be named benchmark_name:

 void benchmark_stdio_write_test() {}

 with UDA:

 @benchmark(stdio write test) void benchStdioWrite();

 Of course you still need that sheduleBenchmarks mixin in every module
 and of course it'd be nice to avoid that. But UDAs are already a big
 step forward.


Consider that you can use a tuple generated elsewhere for a UDA:

[tp] void foo();

where tp is a tuple. You can even grab the attributes from another symbol, turn 
them into a tuple, and apply the tuple as an attribute to a new symbol. Tuples 
can, of course, be sliced and concatenated.


In other words, by using tuples, you can encapsulate what the attributes 
expand to in the same way you can change target code by changing the definition 
of user defined types.


Re: User Defined Attributes

2012-11-06 Thread Walter Bright

On 11/6/2012 8:02 AM, Tove wrote:

On Tuesday, 6 November 2012 at 15:19:53 UTC, Walter Bright wrote:

On 11/6/2012 7:14 AM, Tove wrote:

Hmmm, actually it doesn't work in plain function/block scope either.


Right, I don't see a compelling purpose for that, either.


Hmm, what about library based GC annotations?

[GC.NoScan] int* local_p;



I have no idea how you could make that work.


Re: User Defined Attributes

2012-11-06 Thread deadalnix

Le 06/11/2012 09:20, Sönke Ludwig a écrit :

Wow, that's a surprise! Just yesterday I was thinking that it would be
really nice to have them for a piece of code ;)

But shouldn't we keep the syntax closer to normal attributes and other
languages(*)? I see a lot of arguments for doing that, with the only
counter-argument that they would be in the same namespace as the
built-in attributes (which should not be that bad, as this is very low
level language stuff).

(*) i.e. @mytype or @(string) and without the '[]'


+1

In addition, this is [] thing will require lookahead when parsing to 
detect if we have an expression (array literal) or a declaration.


Re: User Defined Attributes

2012-11-06 Thread deadalnix

Le 06/11/2012 08:55, Walter Bright a écrit :

References:

http://www.digitalmars.com/d/archives/digitalmars/D/Custom_attributes_again_163042.html


http://www.digitalmars.com/d/archives/digitalmars/D/custom_attribute_proposal_yeah_another_one_163246.html


Inspired by a gallon of coffee, I decided to get it implemented. It's
simple, based on what D already does (CTFE and heterogeneous tuples),
easy to implement, easy to understand, and doesn't break anything. It
should do everything asked for in the above references (except it's not
a type constructor).

You can download it here and try it out:

http://ftp.digitalmars.com/dmd2beta.zip

As a bonus, that beta also can generate Win64 executables, and you can
even symbolically debug them with VS! (Thanks to Rainer Schütze for his
invaluable help with that).

Here's the rather skimpy and lame spec I banged out:
=
User Defined Attributes
---

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.

Grammatically, a UDA is a StorageClass:

StorageClass:
UserDefinedAttribute

UserDefinedAttribute:
[ ArgumentList ]

And looks like:

[ 3 ] int a;
[ string, 7 ]: int b;

If there are multiple UDAs in scope for a declaration, they are
concatenated:

[ 1 ] {
[ 2 ] int a; // has UDA's [1,2]
[ string ] int b; // has UDA's [1,string]
}

UDA's can be extracted into an expression tuple using __traits:

[ 'c' ] string s;
pragma(msg, __traits(getAttributes, s));

prints:

tuple('c')

If there are no user defined attributes for the symbol, an empty tuple
is returned.
The expression tuple can be turned into a manipulatable tuple:

template Tuple(T...) {
alias T Tuple;
}

enum EEE = 7;
[hello] struct SSS { }
[3] { [4][EEE][SSS] int foo; }

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

pragma(msg, TP);
pragma(msg, TP[2]);

prints:

tuple(3,4,7,(SSS))
7

and of course the tuple types can be used to declare things:

TP[3] a; // a is declared as an SSS

The attribute of the type name is not the same as the attribute of the
variable:

pragma(msg, __traits(getAttributes, typeof(a));

prints:

tuple(hello)

Of course, the real value of UDA's is to be able to create user defined
types with
specific values. Having attribute values of basic types does not scale.
The attribute tuples can be manipulated like any other tuple, and
can be passed as the argument list to a template.

Whether the attributes are values or types is up to the user, and
whether later
attributes accumulate or override earlier ones is also up to how the
user interprets them.


OK, I may break all the happiness of that news but . . .

Tuple in D is notoriously known to be a badly designed feature. Basing 
more stuff on that just because we have them is short sighted and will 
only result in D's tuples being broken forever, several tuples 
implementations for more user confusion, or future major breakage.


We still don't have any scheme for a stable D, feature testing or 
whatever, so everybody should be prepared for many new ICE (or even more 
fun, bugs). After we all love them or we wouldn't be using D ! Who need 
a programming language to be stable or reliable ?


Surprise feature ! Yaw, no wonder D's toolchain is so wonderfull ! Let's 
not talk these awesome static code analysis tools, java would become 
jealous.


BTW, I don't really like that syntax, but really, that isn't important.


Re: Remus

2012-11-06 Thread Namespace
I'm learning the D language right now, and I can not say that 
I've missed any of these things. They may offer some 'syntactic 
sugar', but the D is very expressive anyway. Ex: for safe 
invocation I would use an assert/enforce anyway if there is a 
chance the object is null. The 'import package' whould be 
usefull though...


Which language(s) did you use before? Java? ;)



Re: User Defined Attributes

2012-11-06 Thread deadalnix

Le 06/11/2012 10:07, Walter Bright a écrit :

n 11/6/2012 12:59 AM, Jakob Ovrum wrote:
  Problem is that there's no way to do this without having the user
specify which
  modules it should work for, like:
 
  import attributes;
  import a, b, c;
 
  static this() // This code cannot be automated.
  {
  initAttributes!a();
  initAttributes!b();
  initAttributes!c();
  }
 

Is that really a problem?


I'm not sure. How can AOP be implemented on top of that ?


Re: User Defined Attributes

2012-11-06 Thread Walter Bright

On 11/6/2012 8:23 AM, bearophile wrote:

Supporting annotations for function arguments is probably an important 
sub-feature.


It would be a significant extension, and so I'd like to see a compelling use 
case first.




Yesterday I was discussing about the bug-prone nature of foreach loops on a
struct array, and one of the solutions I've suggested was a user-defined
annotation for the programmer to denote that she wants to modify just the copy:

struct Foo {}
Foo[10] foos;
foreach (@copy f; foos) { ... }

With UDA syntax:

foreach ([Copy] f; foos) { ... }
Or:
foreach (@(Copy) f; foos) { ... }

But I think there's no way to tell the compiler to give a compile-time error if
such annotation is not present there (unless there's ref).


User defined attributes cannot invent new semantics for the language. And 
besides, 'ref' already does what you suggest.




Re: User Defined Attributes

2012-11-06 Thread dennis luehring
Am 06.11.2012 16:18, schrieb Walter Bright: On 11/6/2012 6:30 AM, 
dennis luehring wrote:

Am 06.11.2012 14:14, schrieb Adam D. Ruppe:
On Tuesday, 6 November 2012 at 07:55:51 UTC, Walter Bright wrote:
User Defined Attributes (UDA) are compile time expressions that
can be attached to a declaration.
   
Hmmm, it didn't work on the most important place for my use case,
function parameters:
   
void a([test] int foo) {
  pragma(msg, __traits(getAttributes, foo));
}
   
sad - but its still very young feature :)
   
im using something like an description on my methods to describe 
parameter
features for an resource manager - something like read, 
write, copy,

read_write etc.
 But there's already out=write, read=all of them, read_write=ref, 
copy=not a ref

 or an out.

and now expand that to an higher level manager that use such information 
for implementing(generating) runtime loading and locking strategies in a 
tree/graph based environment - based on the parameters needs ... i've 
got something like that in C++ using its own interface description 
language and an generator



 I don't know what use UDAs would be for parameters.


exact the same as for every other symbol - it enriches the semantic 
meaning of that symbol :)


Re: User Defined Attributes

2012-11-06 Thread deadalnix

Le 06/11/2012 17:46, Walter Bright a écrit :

On 11/6/2012 8:27 AM, deadalnix wrote:

OK, I may break all the happiness of that news but . . .

Tuple in D is notoriously known to be a badly designed feature. Basing
more
stuff on that just because we have them is short sighted and will only
result in
D's tuples being broken forever, several tuples implementations for
more user
confusion, or future major breakage.


The only real trouble with tuples is that functions can't return them.



If it is the only problem, we have a pandemic spread of hallucinogen 
trance amongs D users.





We still don't have any scheme for a stable D, feature testing or
whatever,


Are you aware of the test suite and the auto-tester?



Yes, I'm also aware I hit compiler bugs on a daily basis, that my 
codebase is full of workaround on some of them.





Let's not talk these awesome static code analysis tools, java would
become jealous.


I have no idea what your point is.


My point is that we have no tooling. Project exists, but they all ends 
up dead at some point or ends up not caring about compatibility that 
much (I'm aware of at least 3 serious D like projects that dropped dmd 
compatibility after spending quite a lot of time on it).


The situation is really bad in that regard (many stuff are 
implementation defined, or even not defined at all because the 
implementation is known to be buggy), and adding surprise, half 
specified features are really not helping.


If you have no idea what my point is, I'm probably wasting my time 
working on D.


Re: User Defined Attributes

2012-11-06 Thread deadalnix

Le 06/11/2012 17:37, Walter Bright a écrit :

On 11/6/2012 8:29 AM, deadalnix wrote:

In addition, this is [] thing will require lookahead when parsing to
detect if
we have an expression (array literal) or a declaration.


Not really, as an array literal starting an expression is kinda
meaningless,


Not with UFCS.


Re: User Defined Attributes

2012-11-06 Thread David Nadlinger

On Tuesday, 6 November 2012 at 08:26:14 UTC, Walter Bright wrote:
We can debate the syntax. I don't have a store set by this one. 
I was more interested in getting the semantics right. Anyhow, 
it's nice to have a working prototype to experiment with rather 
than a paper airplane.


Yes, it is nice to have a working prototype indeed. What is not 
so nice in my opinion, however, is that this first prototype 
straight to Git master, without any prior evaluation, at a time 
where the general goal is to stabilize the language.


What if the implementation doesn't pan out as planned? Do you 
want to delay the next release until the new feature has become 
stable? It can be a big mess to hastily revert the commits again 
after the same areas might have been touched by other, unrelated 
sets of changes.


This is exactly what branches are good for. People can experiment 
with the new additions and shortcomings can be fixed, and then, 
if everything looks solid, the branch can be merged back into 
master – without affecting work on the main branch in the 
meantime (it has been three months since the last release, and 
there are quite a few open regressions).


Even Andrei submits pull requests for any non-trivial Phobos 
changes. Might I suggest adopting a similar policy for DMD, at 
least when language changes/additions are concerned?


David


Re: User Defined Attributes

2012-11-06 Thread Walter Bright

On 11/6/2012 8:47 AM, bearophile wrote:

Walter Bright:


It would be a significant extension, and so I'd like to see a compelling use
case first.


Right. Combined with the trait to read function arguments, it's useful to add
semantics to function arguments. This is good.


Ok, I ask again, what use case for a UDA is there for function parameters? (Note 
that IDL isn't it, as D already has enough parameter attributes to support IDL.)




User defined attributes cannot invent new semantics for the language.


Right, that's my point :-)


So it cannot work for the use case you suggested. I'm still asking for a 
compelling use case.




And besides, 'ref' already does what you suggest.


Nope. I have discussed the topic here:
http://forum.dlang.org/thread/znbtczbgipqqzllaf...@forum.dlang.org

ref is useful to denote Case2 of that post of mine. But the @copy annotation I
was talking here is the very uncommon (but unfortunately often used by mistake,
and common source of bugs) Case3.


I don't see how having the user add a UDA is better than having the user add 
const.


Re: User Defined Attributes

2012-11-06 Thread deadalnix

Le 06/11/2012 16:15, Walter Bright a écrit :

On 11/6/2012 5:14 AM, Adam D. Ruppe wrote:

Hmmm, it didn't work on the most important place for my use case,
function
parameters:


It didn't occur to me to enable that.



It should work everywhere or not work at all.


Re: User Defined Attributes

2012-11-06 Thread John Chapman

Enjoying playing with the new stuff.

UDAs appear to work on class, struct and global methods, but not 
interface methods. Any reason for the omission? Would be great to 
have them on interface methods too - for example to define COM 
dispids.


Re: User Defined Attributes

2012-11-06 Thread Walter Bright

On 11/6/2012 9:01 AM, deadalnix wrote:

Le 06/11/2012 17:37, Walter Bright a écrit :

On 11/6/2012 8:29 AM, deadalnix wrote:

In addition, this is [] thing will require lookahead when parsing to
detect if
we have an expression (array literal) or a declaration.


Not really, as an array literal starting an expression is kinda
meaningless,


Not with UFCS.


You have a point.


Re: User Defined Attributes

2012-11-06 Thread Walter Bright

On 11/6/2012 9:00 AM, dennis luehring wrote:

1. what if my needs are beyond D?

for example my idl allows me to define a type based query source for parameters

CalculateStuff( TypeX [source=\\placement\(typeA|typeB|typeC)] my_usage )

this defines the source of assignable objects to this method


Has this capability ever been used?



2. what is the reason for stopping right before parameters? (except less coding
on your side)


It adds significant complexity. I don't think it's a good idea to add 
significant complexity to the language without a compelling use case. It needs 
to be something more than just being nice.




Re: User Defined Attributes

2012-11-06 Thread Adam D. Ruppe

On Tuesday, 6 November 2012 at 16:41:22 UTC, Walter Bright wrote:
It would be a significant extension, and so I'd like to see a 
compelling use case first.


What do you consider to be compelling use cases for UDAs on 
functions?


Going back to the links on the original post, we have:

I have numerous systems that need to scan the module for things 
marked accordingly to automate bindings to their respective 
systems.


Putting them on parameters also helps with this. Script languages 
have to deal with parameters. Editors might. And, of course, I've 
already talked about automatic UI generation.



Here's another one: named parameters. Of course, there's D names, 
but suppose you have to hook into another naming scheme that uses 
characters that aren't valid D names?


An external system might send you log-in?user-id=foo. You are 
doing a library to automatically call a class:


class Handler {
  [ExternalName(log-in)] /* we can do this now */
void logIn([ExternalName(user-id)] string userId) {}
  /* but the parameter, which is the same concept, doesn't 
work */

}





Re: User Defined Attributes

2012-11-06 Thread Walter Bright

On 11/6/2012 9:06 AM, deadalnix wrote: Le 06/11/2012 16:15, Walter Bright a 
écrit :
 On 11/6/2012 5:14 AM, Adam D. Ruppe wrote:
 Hmmm, it didn't work on the most important place for my use case,
 function
 parameters:

 It didn't occur to me to enable that.


 It should work everywhere or not work at all.

You can't have @pure attributes on function parameters, either. Parameters don't 
work like regular declarations, never have, and I don't know of a language where 
they do. They even have a different grammar.




Re: User Defined Attributes

2012-11-06 Thread Walter Bright

On 11/6/2012 9:07 AM, John Chapman wrote:

UDAs appear to work on class, struct and global methods, but not interface
methods. Any reason for the omission? Would be great to have them on interface
methods too - for example to define COM dispids.


Can you show an example code snippet?


Re: User Defined Attributes

2012-11-06 Thread Adam D. Ruppe

On Tuesday, 6 November 2012 at 17:16:34 UTC, Adam D. Ruppe wrote:

  [ExternalName(log-in)] /* we can do this now */
void logIn([ExternalName(user-id)] string userId)



BTW we could conceivably do:

[ExternalName(log-in),
ParameterAttribute!(userId)(ExternalName(user-id)]
   void logIn(string userId) {}


Where the ParameterAttribute simply matches up the param by name 
or by position (if you pass an int instead of string) and puts 
the other argument in that map.


When you scan the function for attributes, you keep your eye open 
for that ParameterAttribute thingy and match it up in the library.



So if it is too painful to put it in the compiler, we could make 
it work in the library.


Re: User Defined Attributes

2012-11-06 Thread dennis luehring
Am 06.11.2012 18:14, schrieb Walter Bright: On 11/6/2012 9:00 AM, 
dennis luehring wrote:

 1. what if my needs are beyond D?

 for example my idl allows me to define a type based query source for 
parameters


 CalculateStuff( TypeX [source=\\placement\(typeA|typeB|typeC)] 
my_usage )


 this defines the source of assignable objects to this method

 Has this capability ever been used?

all the while - the complete object-to-object lifecycle of composits 
etc. is managed by this - no coded object creation is happening


its partially based on the naked object pattern

the next step will be a complete managed(and hopefully more efficient) 
loading/locking strategy - but still in around 800k lines of C++ :(


Re: User Defined Attributes

2012-11-06 Thread dennis luehring

Am 06.11.2012 18:32, schrieb David Nadlinger:

On Tuesday, 6 November 2012 at 17:00:27 UTC, Walter Bright wrote:

Ok, I ask again, what use case for a UDA is there for function
parameters? (Note that IDL isn't it, as D already has enough
parameter attributes to support IDL.)


What »IDL« are you referring to here? At least as far as I am
aware, IDL usually just refers to an »interface definition
language« in general, so I'm not quite sure what you mean if you
are talking about »enough to support IDL«.

Actually, the Thrift IDL would be a perfect example of how
attributes on parameters can be useful. A simple service
definition in a .thrift could look like this:

---
service Calculator {
 i32 calculate(1:i32 a, 2:i32 b, 3:Op op)
}


perfect example - thx alot



Re: User Defined Attributes

2012-11-06 Thread Jacob Carlborg

On 2012-11-06 17:22, Walter Bright wrote:


Consider that you can use a tuple generated elsewhere for a UDA:

[tp] void foo();

where tp is a tuple. You can even grab the attributes from another
symbol, turn them into a tuple, and apply the tuple as an attribute to a
new symbol. Tuples can, of course, be sliced and concatenated.

In other words, by using tuples, you can encapsulate what the
attributes expand to in the same way you can change target code by
changing the definition of user defined types.


Then allow something like this:

@(tp)

Or

@foo(tp)

--
/Jacob Carlborg


Re: User Defined Attributes

2012-11-06 Thread Walter Bright

On 11/6/2012 9:52 AM, bearophile wrote:

// Case3 (uncommon)
void main() {
 auto data = [0, 1, 2, 3];
 foreach (@copy x; data)
 writeln(++x);
}


x is a value type, and it is already copied. And if you did want to copy it,

foreach (x; data)
{   auto copy = x;
writeln(++copy);
}

I don't see what the annotation buys you, even if it could be made to work.



Re: User Defined Attributes

2012-11-06 Thread Walter Bright
On 11/6/2012 10:01 AM, David Nadlinger wrote: On Tuesday, 6 November 2012 at 
17:51:28 UTC, Walter Bright wrote:

 On 11/6/2012 9:32 AM, David Nadlinger wrote:
 service Calculator {
i32 calculate(1:i32 a, 2:i32 b, 3:Op op)

 What does this mean? That 'a' is the first parameter and has type i32?

 It means that ›a‹ has type i32

Ok, but a type is not a UDA g.

 and is the parameter with ID 1. The parameter
 list could have also been (42:i32 a, 5:i32 b, 1:Op op). If no ids are 
specified,
 negative ones are auto-assigned by the compiler, starting from -1.

Why isn't 'a' the ID?



Re: User Defined Attributes

2012-11-06 Thread Jacob Carlborg

On 2012-11-06 18:00, David Nadlinger wrote:


Yes, it is nice to have a working prototype indeed. What is not so nice
in my opinion, however, is that this first prototype straight to Git
master, without any prior evaluation, at a time where the general goal
is to stabilize the language.


Yes, very good point. I don't see why this hasn't been done before, it's 
dead easy. Just use:


$ git checkout -b uda
# code
$ git commit -a -m Add support for user defined attributes
$ git push origin uda

Walter, why aren't you using branches for these kind of things?

--
/Jacob Carlborg


Re: User Defined Attributes

2012-11-06 Thread David Nadlinger

On Tuesday, 6 November 2012 at 18:06:15 UTC, Walter Bright wrote:
On 11/6/2012 10:01 AM, David Nadlinger wrote: On Tuesday, 6 
November 2012 at 17:51:28 UTC, Walter Bright wrote:

 On 11/6/2012 9:32 AM, David Nadlinger wrote:
 service Calculator {
i32 calculate(1:i32 a, 2:i32 b, 3:Op op)

 What does this mean? That 'a' is the first parameter and has
type i32?

 It means that ›a‹ has type i32

Ok, but a type is not a UDA g.


That was never my point. I could have also just said »Parameters 
to Thrift RPC methods have numerical IDs«, but I though a code 
example might be clearer. Apparently, I was wrong. ;)



Why isn't 'a' the ID?
a is just a name used for documentation purposes – they show up 
in target language code generated by the Thrift compiler from the 
IDL file, for implementations which rely on code generation [1].


On the wire, all struct fields and method parameters are tagged 
with integer IDs, and those are actually what's used for 
(de-)serializations. This use of IDs is a common feature of 
»high-performance« RPC protocols designed to support interface 
evolution, e.g. Google's protobuf makes use of them as well.


David


[1] The compiler module for D only translates type and service 
definitions to D structs/interfaces, the rest happens using CTFE 
magic, which enables use of Thrift without writing .thrift files 
(in fact, they can be generated _from_ D code using CTFE). In 
theory, the compiler could be completely replaced using 
ImportStatements and CTFE, but I never got that out of the 
prototype stage due to compiler bugs.


Re: User Defined Attributes

2012-11-06 Thread Walter Bright

On 11/6/2012 10:01 AM, Jacob Carlborg wrote:

What's the issue with the name scoping system? That the user defined attributes
will conflict with already existing attributes? You'll have the same problem
with keywords. Perhaps that's why attributes where created, to have a new
namespace for keywords. Even if they might not be the same internally for the
compiler it's the same for the user/developer.


Then all UDAs must exist in some shared global name space, and scoping and 
encapsulation becomes like it is in C, i.e. 
every_body_writes_their_names_like_this and hopes it doesn't conflict with 
someone else's names.






Re: User Defined Attributes

2012-11-06 Thread Jacob Carlborg

On 2012-11-06 19:16, Walter Bright wrote:


Then all UDAs must exist in some shared global name space, and scoping
and encapsulation becomes like it is in C, i.e.
every_body_writes_their_names_like_this and hopes it doesn't conflict
with someone else's names.


No, what's the difference between this:

@every_body_writes_their_names_like_this int a;

And

[every_body_writes_their_names_like_this] int a;

None.

--
/Jacob Carlborg


Re: User Defined Attributes

2012-11-06 Thread deadalnix

Le 06/11/2012 19:02, Walter Bright a écrit :

On 11/6/2012 9:34 AM, dennis luehring wrote:

can't you please give us a bad-usage example why it is/should be
forbidden to
use UDA on parameters (and please - we are not talking about pure, in,
out and
stuff like that)


I believe this is the wrong question. For a new feature, the question
should be why should it be included, not why shouldn't it be included.



No. It is needed to annotate symbols, uses cases are numerous. Now, if 
an exception is added, the exception should be justified.


Re: User Defined Attributes

2012-11-06 Thread David Nadlinger

On Tuesday, 6 November 2012 at 18:16:15 UTC, Walter Bright wrote:
Then all UDAs must exist in some shared global name space, and 
scoping and encapsulation becomes like it is in C, i.e. 
every_body_writes_their_names_like_this and hopes it doesn't 
conflict with someone else's names.


You are right, UDAs must definitely leverage D's module system 
for encapsulation/disambiguation. Use of string literals (which 
are intrinsically »global«) as annotations needs to be 
explicitly discouraged.


David


Re: User Defined Attributes

2012-11-06 Thread deadalnix

Le 06/11/2012 19:19, Jacob Carlborg a écrit :

On 2012-11-06 19:16, Walter Bright wrote:


Then all UDAs must exist in some shared global name space, and scoping
and encapsulation becomes like it is in C, i.e.
every_body_writes_their_names_like_this and hopes it doesn't conflict
with someone else's names.


No, what's the difference between this:

@every_body_writes_their_names_like_this int a;

And

[every_body_writes_their_names_like_this] int a;

None.



Let me suggest what have already been suggested by others :

@identifier(parameters)

identifier is resolved as any identifier is. It allow for 
disambiguation. It also allow for a lib to provide its own attributes 
types without colliding which other (it is easy to filter the tuple for 
attribute with the right type).


Re: User Defined Attributes

2012-11-06 Thread Paulo Pinto

Am 06.11.2012 17:41, schrieb Walter Bright:

On 11/6/2012 8:23 AM, bearophile wrote:

Supporting annotations for function arguments is probably an important
sub-feature.


It would be a significant extension, and so I'd like to see a compelling
use case first.




Having seen how annotations for function arguments in Java 8 might look 
like, and the annotations everywhere that we have in the enterprise 
frameworks, I am weary of such support.


--
Paulo



Re: User Defined Attributes

2012-11-06 Thread Walter Bright

On 11/6/2012 10:19 AM, Jacob Carlborg wrote:

No, what's the difference between this:

@every_body_writes_their_names_like_this int a;

And

[every_body_writes_their_names_like_this] int a;

None.



You're right, there is none. That's why using type names as attributes is more 
scalable and robust.


I understand your desire to have attributes be implicitly declared, but I think 
that implicit declarations have historically been seductive, and much later were 
realized to be a mistake. This pattern has happened over and over :-)


For example:

   @seperate

and sometime later:

   @separate

How long will it be before that bug is noticed?


Re: User Defined Attributes

2012-11-06 Thread Paulo Pinto

Am 06.11.2012 17:26, schrieb Walter Bright:

On 11/6/2012 8:02 AM, Tove wrote:

On Tuesday, 6 November 2012 at 15:19:53 UTC, Walter Bright wrote:

On 11/6/2012 7:14 AM, Tove wrote:

Hmmm, actually it doesn't work in plain function/block scope either.


Right, I don't see a compelling purpose for that, either.


Hmm, what about library based GC annotations?

[GC.NoScan] int* local_p;



I have no idea how you could make that work.


I can only see it work if the runtime is aware of magic annotations, 
which are kept in the binary.


--
Paulo


Re: User Defined Attributes

2012-11-06 Thread bearophile

Walter Bright:

First of all, assume I know how to use and abuse foreach in all 
the common and uncommon cases. So in this discussion we can 
assume we both know well enough what we are talking about. What I 
am discussing about is a real problem in real D code, a bug-prone 
characteristic of foreach. We may accept the situation like it 
is, and do nothing, or we may want to improve the situation. But 
this doesn't change the fact that there is a problem in the D 
design of foreach loops when you scan an array of structs. This 
problem is recognized by several other persons in the D 
community, it's not a creation of my mind.


That said, let me try again to explain the problem.


// Case3 (uncommon)
void main() {
auto data = [0, 1, 2, 3];
foreach (@copy x; data)
writeln(++x);
}


x is a value type, and it is already copied. And if you did 
want to copy it,


foreach (x; data)
{   auto copy = x;
writeln(++copy);
}

I don't see what the annotation buys you, even if it could be 
made to work.


The point of Case3 is not that I want to copy it again. The 
annotation by itself buys you nothing. But he annotation is not 
meant to be the only change in D. There are two changes that need 
to happen at the same time:



Change1) Make this a compile-time error, this means if you write 
this code, the compiler refuses your code statically. So x 
despite not being const is like being const, because the compiler 
does not let you modify it inside the loop, if you try, it gives 
you an error (so maybe it's simpler to implement this Change1 
really as putting const on default on x even if you don't write 
const there. C# language is designed this way!):


auto data = [1, 2, 3];
foreach (x; data)
x++; // compilation error here


Change2) Introduce an annotation like @mutable to denote Case3 (I 
have replaced @copy with @mutable to make this explanation more 
clear for you, so maybe @mutable is really a better name for this 
idea). This means this is accepted, it's like saying that x is 
not const:


foreach (@mutable x; data)
writeln(++x); // OK



Why I have suggested this pair of changes? The only purpose of 
those two changes is to remove one bug-prone situation from D 
code.


The situation is this:

struct Foo { int x; }
auto data = [Foo(1), Foo(2), Foo(3)];
foreach (f; data)
f.x++;


What is the programmer trying to write there? Was she trying to 
change the structs inside data (Case2)? Or was she trying to 
modify just their copy (Case3)?


The problem is that usually programmers want Case1 or Case2, they 
most times do not want to write a Case3. But it's very easy to 
forget ref. So the programmer wants to write a Case2 but often 
writes a Case3 by mistake.


The combined presence of Change1 and Change2 removes this source 
of errors. Because now if you forget ref the compiler refuses 
your code statically. If you want Case3 you add a @copy. In most 
cases you really meant to use a Case2 so you add ref and the D 
compiler has caught your bug!


If you were trying to write a Case1 you didn't put inside the 
loop code that modifies the struct, so the error of Change1 is 
not triggered and you need no @copy nor ref.



I have written probably 250_000+ lines of good-quality D1/D2 
code, and bugs like this are still present in my code, so I'd 
like to remove them from D once and for all:


struct Foo { int x; }
auto data = [Foo(1), Foo(2), Foo(3)];
foreach (f; data)
f.x++;

Bye,
bearophile


Re: User Defined Attributes

2012-11-06 Thread Max Samukha

On Tuesday, 6 November 2012 at 17:17:50 UTC, Walter Bright wrote:
On 11/6/2012 9:06 AM, deadalnix wrote: Le 06/11/2012 16:15, 
Walter Bright a écrit :

 On 11/6/2012 5:14 AM, Adam D. Ruppe wrote:
 Hmmm, it didn't work on the most important place for my use
case,
 function
 parameters:

 It didn't occur to me to enable that.


 It should work everywhere or not work at all.

You can't have @pure attributes on function parameters, either. 
Parameters don't work like regular declarations, never have, 
and I don't know of a language where they do. They even have a 
different grammar.


C# allows custom attributes on function parameters, including the 
return value. Actually, it allows custom meta-data everywhere. 
See a use case here 
http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshalasattribute.aspx.

I believe Java does the same.


Re: User Defined Attributes

2012-11-06 Thread David Nadlinger

On Tuesday, 6 November 2012 at 18:36:54 UTC, Walter Bright wrote:

For example:

   @seperate

and sometime later:

   @separate

How long will it be before that bug is noticed?


This doesn't put the @-syntax out of the game, though: @attribute 
could just be equivalent to @(attribute) and look up attribute 
in the local scope, following the usual rules. This would look 
much better than the bracket syntax, at least in my opinion, and 
avoid confusion with array literals.


David


Re: User Defined Attributes

2012-11-06 Thread Walter Bright

On 11/6/2012 10:10 AM, Jacob Carlborg wrote:

On 2012-11-06 18:00, David Nadlinger wrote:


Yes, it is nice to have a working prototype indeed. What is not so nice
in my opinion, however, is that this first prototype straight to Git
master, without any prior evaluation, at a time where the general goal
is to stabilize the language.


Yes, very good point. I don't see why this hasn't been done before, it's dead
easy. Just use:

$ git checkout -b uda
# code
$ git commit -a -m Add support for user defined attributes
$ git push origin uda

Walter, why aren't you using branches for these kind of things?



Because I still think in a linear fashion :-)


Re: User Defined Attributes

2012-11-06 Thread Walter Bright

On 11/6/2012 4:18 AM, Max Samukha wrote:

Attributes on overloads are critical. Currently fails:


Found  fixed. Thanks!



  1   2   3   4   >