March 19, 2012
On 3/19/12, Jacob Carlborg <doob@me.com> wrote:
> Yeah, but that will complicate the retrieval of the information.

What is so complicated about extracting fields? Just iterate via .tupleof:

module test;

import std.stdio;
import std.conv;

struct Foo
{
    int x;
    string name;
    mixin NonSerialized!name;
    string lastName;
    mixin NonSerialized!lastName;
    string extra;
}

mixin template NonSerialized(alias field)
{
    mixin("enum __attribute_nonSerialized_" ~ field.mangleof ~ ";");
}

string serialize(T)(T input)
{
    string result;

    foreach (i, field; input.tupleof)
    {
        static if (skipSerialize!(T, input.tupleof[i].mangleof))
            result ~= to!string(typeof(field).init) ~ "\n";
        else
            result ~= to!string(field) ~ "\n";
    }

    return result;
}

template skipSerialize(T, string mangle)
{
	enum bool skipSerialize = __traits(hasMember, T,
"__attribute_nonSerialized_" ~ mangle);
}

void main()
{
    Foo foo = Foo(10, "Foo", "Bar", "Doo");
    string bin = serialize(foo);
    writeln(bin);
}

And by using .init instead of just skipping serialization altogether you can unserialize at a later point even if you end up removing some of the mixins, so you can have some binary-compatibility there.
March 20, 2012
On Monday, 19 March 2012 at 21:00:32 UTC, Andrei Alexandrescu wrote:
> On 3/19/12 3:55 PM, F i L wrote:
>> I think this could get tricky for the compiler to confidently use given
>> that the mixed in enums can collide with existing members (although not
>> likely). Also, if objects are not identified as being unique marked (in
>> the compilers eyes), what specific attribute post-fixes will it be
>> searching for on enums members?
>
> Not a big issue, the name could always contain a uuid which makes collision practically impossibile.
>
> Andrei

And with parameters? Or how about run-time reflection, which is something that should be added eventually for attributes as well (that is, typeid(Blah).getCustomAttributes())? We can't manually add things into the TypeInfo. This is an already ridiculously hackish approach, and it *does not* work for anything besides trivial applications. It is completly unreasonable to expect everything to be done in a library; the compiler exists for a reason and at some point you have to draw the line. Why even bother having an auto keyword? Instead of 'auto a = b + c' you could simply use 'Auto!(b + c) a = b + c'. It is a more extreme example for now, but won't be too much different once more complicated things arise; after all, auto!2 a = 2 is not much different from auto a = 2. Just like it's not too much different for parameterless attributes (even if it is uglier and much more hackish), but once you get into parameters and runtime stuff it becomes just as ugly as the above example.
March 20, 2012
and how to add attribute parameters like DoSerialize(type=packed) for example - very very common in C# attributes and java annotations

http://en.wikipedia.org/wiki/Java_annotation

Am 19.03.2012 22:00, schrieb Andrei Alexandrescu:
> On 3/19/12 3:44 PM, Andrej Mitrovic wrote:
>>  On 3/19/12, Jacob Carlborg<doob@me.com>   wrote:
>>>  * Can be repeated on several fields (with the mixin you can only mixin
>>>  "NonSerialized" once)
>>
>>  When I implemented NonSerialized for Vladimir's json library he made a
>>  suggestion to simply create enums of each field that is not to be
>>  serialized and encode it as "fieldname_nonSerialized". That would
>>  enable using a NonSerialized mixin multiple times.
>>
>>  I've yet to implement it in that way, I ran into some odd bugs but
>>  I'll have a look at this soon. My implementation used a hash lookup
>>  table for the fields, but using enums would make the code even
>>  simpler. Basically:
>>
>>  struct Foo
>>  {
>>       int x;
>>       string name;
>>       mixin(NonSerialized!name);
>>       string lastName;
>>       mixin(NonSerialized!lastName);
>>  }
>>
>>  and this would expand to:
>>  struct Foo
>>  {
>>       int x;
>>       string name;
>>       enum name_nonSerialized;
>>       string lastName;
>>       enum lastName_nonSerialized;
>>  }
>>
>>  So all you'd have to do is use compile-time introspection and a little
>>  bit of string processing to figure out if a field should be serialized
>>  or not.
>
> I salute creative uses of the language over defining new features.
>
> Andrei

March 20, 2012
On 2012-03-19 22:51, Andrej Mitrovic wrote:
> On 3/19/12, Jacob Carlborg<doob@me.com>  wrote:
>> Yeah, but that will complicate the retrieval of the information.
>
> What is so complicated about extracting fields? Just iterate via .tupleof:

It wasn't actually that much more complicated. But now there is one extra enum for each NonSerialized field.

-- 
/Jacob Carlborg
March 20, 2012
On 2012-03-19 22:00, Andrei Alexandrescu wrote:

> I salute creative uses of the language over defining new features.
>
> Andrei

The actual point of user defined attributes it to be able to create domain specific attributes so we don't have to add new features to the language. This is also to have a sane syntax for the attributes.

I think in several cases D could have chose to implement a more general feature but instead implemented a very specific feature or hack.

Example:

If D supported passing delegates to a function after the function call several language features could have been implemented in the library instead.

void synchronized (void delegate () dg)
{
    try
    {
        lock();
        dg();
    }
    finally
        unlock();
}

synchronized {
    // do something
}

In the same way foreach can be implemented in a library function:

void foreach (T) (T[] arr, void delegate (T) dg)
{
    for (size_t i = 0; i < arr.length; i++)
        dg(arr[i]);
}

auto arr = [3, 4, 5];

foreach (arr ; e // this is the parameter to the delegate) {
    writeln(e);
}

-- 
/Jacob Carlborg
March 20, 2012
Jacob Carlborg wrote:
> If D supported passing delegates to a function after the function call several language features could have been implemented in the library instead.
>
> void synchronized (void delegate () dg)
> {
>     try
>     {
>         lock();
>         dg();
>     }
>     finally
>         unlock();
> }
>
> synchronized {
>     // do something
> }
>
> In the same way foreach can be implemented in a library function:
>
> void foreach (T) (T[] arr, void delegate (T) dg)
> {
>     for (size_t i = 0; i < arr.length; i++)
>         dg(arr[i]);
> }
>
> auto arr = [3, 4, 5];
>
> foreach (arr ; e // this is the parameter to the delegate) {
>     writeln(e);
> }

That's pretty slick. D would need delegate inlining + @forceInline before foreach could be expressed this way though.

March 20, 2012
On 2012-03-20 10:49, F i L wrote:

> That's pretty slick. D would need delegate inlining + @forceInline
> before foreach could be expressed this way though.

Yes, but currently, as far as I know, the delegate passed to opApply is not inlined.

-- 
/Jacob Carlborg
March 20, 2012
On 3/20/12 12:50 AM, Kapps wrote:
> On Monday, 19 March 2012 at 21:00:32 UTC, Andrei Alexandrescu wrote:
>> On 3/19/12 3:55 PM, F i L wrote:
>>> I think this could get tricky for the compiler to confidently use given
>>> that the mixed in enums can collide with existing members (although not
>>> likely). Also, if objects are not identified as being unique marked (in
>>> the compilers eyes), what specific attribute post-fixes will it be
>>> searching for on enums members?
>>
>> Not a big issue, the name could always contain a uuid which makes
>> collision practically impossibile.
>>
>> Andrei
>
> And with parameters? Or how about run-time reflection, which is
> something that should be added eventually for attributes as well (that
> is, typeid(Blah).getCustomAttributes())? We can't manually add things
> into the TypeInfo.

Perhaps we should add a field of type Variant[string].

> This is an already ridiculously hackish approach, and
> it *does not* work for anything besides trivial applications. It is
> completly unreasonable to expect everything to be done in a library; the
> compiler exists for a reason and at some point you have to draw the
> line.

I'm afraid I disagree. A targeted language feature definitely makes a library approach inferior, by definition. But adding features is cheating, like printing money is for a government: very tempting, with apparently good short-term benefits, but with devastating cumulative effects.

Also, as I mentioned, the availability of the easy escape hatch of adding a language feature thwarts creativity. Nobody will care to think about and come with idioms that use the language to do great things, if they know a language feature could be always added that makes things "nicer".

I'm not saying this particular feature should or should not be in the language, but I wish our community exercised considerably more restraint when it comes about adding new language features.

> Why even bother having an auto keyword? Instead of 'auto a = b +
> c' you could simply use 'Auto!(b + c) a = b + c'. It is a more extreme
> example for now, but won't be too much different once more complicated
> things arise; after all, auto!2 a = 2 is not much different from auto a
> = 2. Just like it's not too much different for parameterless attributes
> (even if it is uglier and much more hackish), but once you get into
> parameters and runtime stuff it becomes just as ugly as the above example.

I don't think your example with auto is relevant.


Andrei
March 20, 2012
On 3/20/12 1:22 AM, dennis luehring wrote:
> and how to add attribute parameters like DoSerialize(type=packed) for
> example - very very common in C# attributes and java annotations
>
> http://en.wikipedia.org/wiki/Java_annotation

One more argument to the template?

Andrei

March 20, 2012
On 2012-03-20 16:17, Andrei Alexandrescu wrote:
> On 3/20/12 12:50 AM, Kapps wrote:

> Perhaps we should add a field of type Variant[string].

No, not Variant[string] again.

>> This is an already ridiculously hackish approach, and
>> it *does not* work for anything besides trivial applications. It is
>> completly unreasonable to expect everything to be done in a library; the
>> compiler exists for a reason and at some point you have to draw the
>> line.
>
> I'm afraid I disagree. A targeted language feature definitely makes a
> library approach inferior, by definition. But adding features is
> cheating, like printing money is for a government: very tempting, with
> apparently good short-term benefits, but with devastating cumulative
> effects.
>
> Also, as I mentioned, the availability of the easy escape hatch of
> adding a language feature thwarts creativity. Nobody will care to think
> about and come with idioms that use the language to do great things, if
> they know a language feature could be always added that makes things
> "nicer".
>
> I'm not saying this particular feature should or should not be in the
> language, but I wish our community exercised considerably more restraint
> when it comes about adding new language features.

See my reply to one of your other posts:

http://forum.dlang.org/thread/bccwycoexxykfgxvedix@forum.dlang.org?page=9#post-jk9gk8:242t7k:241:40digitalmars.com

-- 
/Jacob Carlborg