March 19, 2012
i don't get the GC relation here?

all attribute values are static const - because they are type-related (static) and read-only, attributes are type orientated not instance orientated

> @GC.NoScan int value;
> @GC this() {}
>
> Compiler Asks library for transformation of unknown @GC
> bool library("@GC this() {anything...}") ->
>
> if the library succeeds it would then transform the string and
> hand back a lowered mixin to the compiler.
>
> mixin("
> this()
> {
>     auto b = [ __traits(allMembers, D) ];
>     foreach( auto a; b) {DO.GC.Stuff...}
>
>     anything...
> }
> ");
>
>



March 19, 2012
On 2012-03-19 01:41, Walter Bright wrote:
> On 3/18/2012 2:58 PM, Jacob Carlborg wrote:
>> Ok, now to the user defined attribute:
>>
>> @attribute class NonSerialized {} // This is what's called a "marker"
>> in Java.
>> It doesn't contain any information, the information is the type itself.
>>
>> @attribute class SerializeAs
>> {
>> string value;
>> }
>>
>> class Base
>> {
>> int x;
>> @SerializeAs(foo) int y;
>> @NonSerialized int c;
>> }
>>
>> @NonSerialized class Sub : Base
>> {
>> int z;
>> }
>>
>> Base sub = new Sub;
>> serialize(sub);
>>
>> In this example the user defined attribute "NonSerialized" indicates
>> that the
>> class shouldn't be serialized. When the serializer is serializing
>> "sub" the
>> compile time type will be "Base" therefore it would need to use runtime
>> reflection to also serialize the fields added in the subclass "Sub".
>> To check if
>> the object should be serialized the serializer need to be able to
>> access user
>> defined attributes using runtime reflection.
>
> I'm sorry, I find this *massively* confusing. What is foo?

It should have been:

@SerializeAs("foo") int y;

"foo" is the name "y" will be serialized with. Just to show an example with an attribute accepting a value.

> Why are you
> serializing something marked "NonSerialized"? I really have no idea what
> is going on with this. What is the serialize() function? How does any of
> this tell you how to serialize an int? How is Base.c also a
> NonSerialized with c in a superclass of it?

This example might not have been the best one. I might not know that "Sub" is marked as "NonSerialized". An instance of "Sub" can be part of another class that is not marked as "NonSerialized".

"serialize" would be the function that performs the serialization. I cannot write a whole serialization in a newsgroup message, can I :)

This example also shows that "NonSerialized" can be applied to individual fields of a class.

This tell how to serialize an int. It tells if a part of an object hierarchy (class, or field) should be serialized or not.

> ??????????????????????????????????
>
> Maybe this is why I don't much care for attributes - it's all just a fog
> to me what is happening.

I think it's quite clear what is happening. But I've might squeezed in too much in a too small example.

-- 
/Jacob Carlborg
March 19, 2012
dennis luehring wrote:
> i don't get the GC relation here?
>
> all attribute values are static const - because they are type-related (static) and read-only, attributes are type orientated not instance orientated

C# doesn't support free-types (everything's wrapped up in classes) so the technique isn't going to be identical. In D, you'd need to be able to declare an attribute on virtually any entity declaration and have the compiler dish out the appropriate code.

Trove's suggesting that the compiler simply looks up user-defined functions associated with <AttributeX> and inject the code into the appropriate place, which I think is a good idea. The problem I see is how to do more advanced structural changes like C# does with [FieldOffset(0)]. Things like:

    @Int.Fast int index;
    assert(index.sizeof == int.sizeof) // always?

which might break the type system, so I'm not sure it's even possible. The compiler might have passed the point of no-return with such attributes.

Regardless, I think was Trove's suggesting would work well.
March 19, 2012
On 19 March 2012 08:46, dennis luehring <dl.soluz@gmx.net> wrote:

>
> attributes does not containing code - there just a (at-runtime) queryable information that can be attached to serveral things (like classes, methods, ...) - think of it like double.epsilon - but extendable by users - thats it, and in the c# world these attribute-definitions tend to be something like an class (but without code)
>
> in c# you can walk by (runtime)reflection through your code and find out if something is annotated with an special attribute and use the configure information and do something with it - call an constructor, open an connection, generated code (at runtime) - whatever you want
>
> its a easy-to-use-buildin-**attribution-system thats it - and people like them because c# do all the big magic by giving developers a bunch of attributes that are then used for stuff like serialization, memory-layout, ...
>
> a compiletime example of this could be:
>
> attribute my_special_attribute
> {
>   int version;
> }
>
> attribute my_special_attribute2
> {
>   string test;
> }
>
> class test
> {
>   [my_special_attribute(version=**2)]
>   int method1();
>
>   [my_special_attribute(version=**2)]
>   [my_special_attribute2(test="**bert")]
>   int method2();
> }
>
> void main()
> {
>  auto b = [ __traits(allMembers, D) ];
>  foreach( auto a; b )
>  {
>    -->attribute query magic
>    -->auto c = [ __traits(attribute("my_**special_attribute", a) ];
>    -->auto c = [ __traits(attribute("my_**special_attribute2", a) ];
>
>    //now we know all methods with my_special_attribute
>    //and speical_special_attribute2 and their content (version=2
>    //and test="bert"
>
>    //now think of an template or mixing that uses this
>    //information for code-generation or something like that
>
>    //thats all
>  }
> }
>

+1 this post


March 19, 2012
On 2012-03-19 09:01, Tove wrote:
> Well I was thinking if we can go one step further than C#, because of
> D:s CTFE... by introducing a call back from the D compiler to the
> library CTFE attribute handler... this way we can hide all reflection
> from the "end user"... and the compiler doesn't need to know anything at
> all, as the library does the semantic lowering.
>
> @GC.NoScan int value;
> @GC this() {}
>
> Compiler Asks library for transformation of unknown @GC
> bool library("@GC this() {anything...}") ->
>
> if the library succeeds it would then transform the string and hand back
> a lowered mixin to the compiler.
>
> mixin("
> this()
> {
> auto b = [ __traits(allMembers, D) ];
> foreach( auto a; b) {DO.GC.Stuff...}
>
> anything...
> }
> ");

That would be cool.

-- 
/Jacob Carlborg
March 19, 2012
Am 19.03.2012 10:03, schrieb F i L:
> dennis luehring wrote:
>>  i don't get the GC relation here?
>>
>>  all attribute values are static const - because they are
>>  type-related (static) and read-only, attributes are type
>>  orientated not instance orientated
>
> C# doesn't support free-types (everything's wrapped up in
> classes) so the technique isn't going to be identical. In D,
> you'd need to be able to declare an attribute on virtually any
> entity declaration and have the compiler dish out the appropriate
> code.
>
> Trove's suggesting that the compiler simply looks up user-defined
> functions associated with<AttributeX>  and inject the code into
> the appropriate place, which I think is a good idea. The problem
> I see is how to do more advanced structural changes like C# does
> with [FieldOffset(0)]. Things like:
>
>       @Int.Fast int index;
>       assert(index.sizeof == int.sizeof) // always?
>
> which might break the type system, so I'm not sure it's even
> possible. The compiler might have passed the point of no-return
> with such attributes.
>
> Regardless, I think was Trove's suggesting would work well.

sound to simple to fit in non trival cases
March 19, 2012
On Sun, 18 Mar 2012 04:03:29 -0400, Walter Bright <newshound2@digitalmars.com> wrote:

> On 3/17/2012 10:01 PM, F i L wrote:
>> Walter Bright wrote:
>>> My impression is it is just obfuscation around a simple lazy initialization
>>> pattern.
>>>
>>> While I can see the abstraction usefulness of compile time attribute metadata,
>>> I am having a hard time seeing what the gain is with runtime attributes over
>>> more traditional techniques.
>>
>> I'm not sure exactly what you mean by runtime attributes. Do you mean the
>> ability to reflect upon attributes at runtime?
>
> I mean there is modifiable-at-runtime, instance-specific data.

I don't think we should go this far with attributes.  If you want to store instance-specific data, we already have a place for that.  I haven't been exactly groking all of this thread, but I understand what attributes are useful for having used them quite a bit in C#.

> Again, I am just not seeing the leap in power with this. It's a mystery to me how a user defined "attribute class" is different in any way from a user defined class, and what advantage special syntax gives a standard pattern for lazy initialization, and why extra attribute fields can't be just, well, fields.

The advantage is it hooks you into the compiler's generation of metadata and runtime type information (i.e. TypeInfo).  It basically allows you to describe your type in ways that the compiler doesn't natively support.  It's purely a type-description thing, I think it has nothing to do with instances.

The serializable example is probably most used because it's one of the most commonly used attributes in C#/Java.  Given that neither has templates, the impact is somewhat greater than in D, but I believe Jacob has quite a bit of experience with serialization of types given that he wrote a serializer for D, so he would be the one I'd ask as to why it's better.  I think another great example is data you can pass to the GC (if we ever get precise scanning).

In a previous life, while using C#, I created a "scripting" system that used objects to define what methods were run during certain test processes (the application managed the automated testing of servers remotely).  The entire script was constructed based on an xml file, and the library that edited/built the script had no access or knowledge of the types it was constructing, it used pure reflection to do everything.  The cool thing (in my mind at least) was, I had a script builder application which "opened" the executable to find all the scripting objects.  It did not need to be recompiled, nor did it directly link with a library having the script objects, because it used reflection to determine everything I needed.  Some specific attributes weren't available in reflection, so I just added some user-defined attributes, and in that way, I was able to affect the metadata to pass information to the script building application.

I think also you can make code more readable and easier to write with attributes, because you can specify/convey information rather than interpreting or making assumptions, or inventing types that have nothing to do with the way the type works.

For example, you could do something like:

struct noSerInt
{
   int _val;
   alias this _val;
}

struct X
{
   noSerInt x; // clue to not serialize x
}

This is extra complication which is not needed while using an instance of X *except* when serializing it.  I think it's cleaner to put this information into the metadata instead of having to re-implement int.  Compare to:

struct X
{
   @noSer int x;
}

Where you can safely ignore the @noSer attribute for most intents and purposes.

I think that the sole purpose of attributes is compile-time generation of compile and run-time query-able data.  Nothing else really makes sense to me.

-Steve
March 19, 2012
exactly my point - thx

Am 19.03.2012 13:31, schrieb Steven Schveighoffer:
> On Sun, 18 Mar 2012 04:03:29 -0400, Walter Bright
> <newshound2@digitalmars.com>  wrote:
>
>>  On 3/17/2012 10:01 PM, F i L wrote:
>>>  Walter Bright wrote:
>>>>  My impression is it is just obfuscation around a simple lazy
>>>>  initialization
>>>>  pattern.
>>>>
>>>>  While I can see the abstraction usefulness of compile time attribute
>>>>  metadata,
>>>>  I am having a hard time seeing what the gain is with runtime
>>>>  attributes over
>>>>  more traditional techniques.
>>>
>>>  I'm not sure exactly what you mean by runtime attributes. Do you mean
>>>  the
>>>  ability to reflect upon attributes at runtime?
>>
>>  I mean there is modifiable-at-runtime, instance-specific data.
>
> I don't think we should go this far with attributes.  If you want to store
> instance-specific data, we already have a place for that.  I haven't been
> exactly groking all of this thread, but I understand what attributes are
> useful for having used them quite a bit in C#.
>
>>  Again, I am just not seeing the leap in power with this. It's a mystery
>>  to me how a user defined "attribute class" is different in any way from
>>  a user defined class, and what advantage special syntax gives a standard
>>  pattern for lazy initialization, and why extra attribute fields can't be
>>  just, well, fields.
>
> The advantage is it hooks you into the compiler's generation of metadata
> and runtime type information (i.e. TypeInfo).  It basically allows you to
> describe your type in ways that the compiler doesn't natively support.
> It's purely a type-description thing, I think it has nothing to do with
> instances.
>
> The serializable example is probably most used because it's one of the
> most commonly used attributes in C#/Java.  Given that neither has
> templates, the impact is somewhat greater than in D, but I believe Jacob
> has quite a bit of experience with serialization of types given that he
> wrote a serializer for D, so he would be the one I'd ask as to why it's
> better.  I think another great example is data you can pass to the GC (if
> we ever get precise scanning).
>
> In a previous life, while using C#, I created a "scripting" system that
> used objects to define what methods were run during certain test processes
> (the application managed the automated testing of servers remotely).  The
> entire script was constructed based on an xml file, and the library that
> edited/built the script had no access or knowledge of the types it was
> constructing, it used pure reflection to do everything.  The cool thing
> (in my mind at least) was, I had a script builder application which
> "opened" the executable to find all the scripting objects.  It did not
> need to be recompiled, nor did it directly link with a library having the
> script objects, because it used reflection to determine everything I
> needed.  Some specific attributes weren't available in reflection, so I
> just added some user-defined attributes, and in that way, I was able to
> affect the metadata to pass information to the script building application.
>
> I think also you can make code more readable and easier to write with
> attributes, because you can specify/convey information rather than
> interpreting or making assumptions, or inventing types that have nothing
> to do with the way the type works.
>
> For example, you could do something like:
>
> struct noSerInt
> {
>      int _val;
>      alias this _val;
> }
>
> struct X
> {
>      noSerInt x; // clue to not serialize x
> }
>
> This is extra complication which is not needed while using an instance of
> X *except* when serializing it.  I think it's cleaner to put this
> information into the metadata instead of having to re-implement int.
> Compare to:
>
> struct X
> {
>      @noSer int x;
> }
>
> Where you can safely ignore the @noSer attribute for most intents and
> purposes.
>
> I think that the sole purpose of attributes is compile-time generation of
> compile and run-time query-able data.  Nothing else really makes sense to
> me.
>
> -Steve


March 19, 2012
On Monday, 19 March 2012 at 00:41:44 UTC, Walter Bright wrote:

> Maybe this is why I don't much care for attributes - it's all just a fog to me what is happening.

Maybe this will help:

http://research.microsoft.com/en-us/um/people/cszypers/events/WCOP2006/rouvoy-wcop-06.pdf

Attribute-Oriented Programming (@OP) is a program-level marking
technique. Basically, this approach allows developers to mark
program elements (e.g., classes, methods, and fields) with
annotations to indicate that they maintain application specific
or domain-specific concerns. For example, a developer may define
a logging annotation and associate it with a method to indicate
that the calls to this method should be logged, or may define a
web service annotation and associate it with a class to indicate
that the class should implement a Web Service. Annotations
separate application’s business logic from middleware-specific
or domain-specific concerns (e.g., logging and web service
functions). By hiding the implementation details of those
semantics from program code, annotations increase the level of
programming abstraction and reduce programming complexity,
resulting in simpler and more readable programs. The program
elements associated with annotations are transformed to more
detailed program code by a supporting generation engine. For
example, a generation
engine may insert logging code into the methods associated with a
logging annotation. Dependencies on the underlying middleware are
thus replaced by annotations, acting as weak references — i.e.,
references that are not mandatory for the application. This means
that the evolution of the underlying middleware is taken into
account by the generation engine and let the program code
unchanged.
March 19, 2012
On 2012-03-19 13:31, Steven Schveighoffer wrote:
> On Sun, 18 Mar 2012 04:03:29 -0400, Walter Bright
>> I mean there is modifiable-at-runtime, instance-specific data.
>
> I don't think we should go this far with attributes. If you want to
> store instance-specific data, we already have a place for that. I
> haven't been exactly groking all of this thread, but I understand what
> attributes are useful for having used them quite a bit in C#.

I agree.

>> Again, I am just not seeing the leap in power with this. It's a
>> mystery to me how a user defined "attribute class" is different in any
>> way from a user defined class, and what advantage special syntax gives
>> a standard pattern for lazy initialization, and why extra attribute
>> fields can't be just, well, fields.
>
> The advantage is it hooks you into the compiler's generation of metadata
> and runtime type information (i.e. TypeInfo). It basically allows you to
> describe your type in ways that the compiler doesn't natively support.
> It's purely a type-description thing, I think it has nothing to do with
> instances.
>
> The serializable example is probably most used because it's one of the
> most commonly used attributes in C#/Java. Given that neither has
> templates, the impact is somewhat greater than in D, but I believe Jacob
> has quite a bit of experience with serialization of types given that he
> wrote a serializer for D, so he would be the one I'd ask as to why it's
> better. I think another great example is data you can pass to the GC (if
> we ever get precise scanning).

For the serialization example I think it's mostly a syntactic enhancement. It would also be an enhancement when accessing the attributes.

class Foo {
    int a;
    @NonSerialized int b;
}

class Bar
{
    int a;
    int b;
    mixin NonSerialized!(b);
}

The advantage the attribute has is:

* Better syntax, more readable
* Shows up in the documentation of "b".
* Can be repeated on several fields (with the mixin you can only mixin "NonSerialized" once)
* Easier to access the attribute
* No information is added to the type itself. It would be added to the metadata of the type, i.e. TypeInfo

But I see many other cases where attributes would work better than mixins.

> In a previous life, while using C#, I created a "scripting" system that
> used objects to define what methods were run during certain test
> processes (the application managed the automated testing of servers
> remotely). The entire script was constructed based on an xml file, and
> the library that edited/built the script had no access or knowledge of
> the types it was constructing, it used pure reflection to do everything.
> The cool thing (in my mind at least) was, I had a script builder
> application which "opened" the executable to find all the scripting
> objects. It did not need to be recompiled, nor did it directly link with
> a library having the script objects, because it used reflection to
> determine everything I needed. Some specific attributes weren't
> available in reflection, so I just added some user-defined attributes,
> and in that way, I was able to affect the metadata to pass information
> to the script building application.
>
> I think also you can make code more readable and easier to write with
> attributes, because you can specify/convey information rather than
> interpreting or making assumptions, or inventing types that have nothing
> to do with the way the type works.
>
> For example, you could do something like:
>
> struct noSerInt
> {
> int _val;
> alias this _val;
> }
>
> struct X
> {
> noSerInt x; // clue to not serialize x
> }
>
> This is extra complication which is not needed while using an instance
> of X *except* when serializing it. I think it's cleaner to put this
> information into the metadata instead of having to re-implement int.
> Compare to:
>
> struct X
> {
> @noSer int x;
> }
>
> Where you can safely ignore the @noSer attribute for most intents and
> purposes.
>
> I think that the sole purpose of attributes is compile-time generation
> of compile and run-time query-able data. Nothing else really makes sense
> to me.
>
> -Steve

Very well explained.

-- 
/Jacob Carlborg