March 21, 2012
On 2012-03-21 15:02, Adam D. Ruppe wrote:
> On Wednesday, 21 March 2012 at 08:08:12 UTC, Jacob Carlborg wrote:
>> That's basically my initial proposal and how annotations work in Java.
>
> Cool. I did not realize that.

Here's my proposal:

http://forum.dlang.org/thread/bccwycoexxykfgxvedix@forum.dlang.org?page=3#post-jk2d4t:242ban:241:40digitalmars.com

-- 
/Jacob Carlborg
March 21, 2012
On 3/21/12 9:57 AM, Jacob Carlborg wrote:
> On 2012-03-21 14:54, Steven Schveighoffer wrote:
>> On Tue, 20 Mar 2012 12:16:41 -0400, Andrei Alexandrescu
>> <SeeWebsiteForEmail@erdani.org> wrote:
>>
>>> Maybe there's a better approach than flectioned. Consider the language
>>> is frozen solid. How would you solve problems with it?
>>
>> I think the closest anyone has come is Jacob, with his orange library.
>> Maybe he can respond to this point.
>>
>> -Steve
>
> With Orange I'm doing everything with compile time reflection.
> Flectioned was all about runtime reflection. It's possible to replace
> methods with flectioned at runtime and do a lot of crazy things.
>
> In Orange I'm using mixins, tupleof and stringof to accomplish most of
> the compile time reflection. Example:
>
> class Foo
> {
> int a;
> int b;
>
> mixin NonSerialized!(b);
> }

I think the liability here is that b needs to appear in two places, once in the declaration proper and then in the NonSerialized part. (A possible advantage is that sometimes it may be advantageous to keep all symbols with a specific attribute in one place.) A possibility would be to make the mixin expand to the field and the metadata at once.

> serialize(new Foo);
>
> "mixin NonSerialized!(b);" is expanded to:
>
> static const __nonSerialized = ["a"];
>
> The fields are enumerated and serialized using tupleof. It also checks
> all structs and classes if they have "__nonSerialized" defined.

Did you mean

static const __nonSerialized = ["b"];

?

In case there are several non-serialized variables, how do you avoid clashes between different definitions of __nonSerialized?


Thanks,

Andrei
March 21, 2012
On Wednesday, 21 March 2012 at 13:54:29 UTC, Steven Schveighoffer wrote:
> I think the closest anyone has come is Jacob, with his orange library.  Maybe he can respond to this point.

I have some runtime reflection in web.d, but the way I do
it is to build up the info at startup, and there's a
special field in the class to hold it.

simplified:

struct Reflection {
   string name;
   ClassInfo[string] objects;
   FunctionInfo[string] functions;
   // etc
}
class ApiProvider { immutable(Reflection)* reflection; }
immutable(Reflection)* prepareReflection(T)(T t) {
   Reflection* r = new Reflection();
   foreach(member; __traits(allMembers, T))
          static if(type..)
                r.typeInfo[member] = prepareReflection(getMember);
}


To call functions, it makes a wrapper that converts
strings to the right types in a ParameterTypeTuple:

functionInfo.caller = wrap!func;

string delegate(string[][string]) wrap(alias func)() {
   return delegate string(string[][string] uriArgs) {
              foreach(type; ParameterTypeTuple!func)
                       blah = to!typeof(blah)(uriArgs[name]);

              return to!string(func(args));
   }
}

and so on. Of course, the real thing is a lot longer than
this, but you can see the idea.



Once it is all populated at startup, you can do:

myobj.reflection.functions["cool"].call(decodeUriVars("sweet=yes&awesome=def"));


and have it work.
March 21, 2012
Andrei Alexandrescu wrote:
> In case there are several non-serialized variables, how do you avoid clashes between different definitions of __nonSerialized?

struct A {
   int a, b;
   mixin NonSerialized!(a, b);
}

static const __nonSerialized = ["a", "b"];

March 21, 2012
On Wednesday, 21 March 2012 at 15:20:35 UTC, F i L wrote:
> Andrei Alexandrescu wrote:
>> In case there are several non-serialized variables, how do you avoid clashes between different definitions of __nonSerialized?
>
> struct A {
>    int a, b;
>    mixin NonSerialized!(a, b);
> }
>
> static const __nonSerialized = ["a", "b"];

Also, if where meant how could you store multiple types, you could just use an Associative Array:

struct A {
  int a;
  float b;
  mixin NonSerialized!(a, b);
}

static const __nonSerialized = ["int":"a", "int":"b"];


March 21, 2012
> static const __nonSerialized = ["int":"a", "int":"b"];

Typo, I meant: ["int":"a", "float":"b"];

March 21, 2012
On Wednesday, 21 March 2012 at 15:02:15 UTC, Jacob Carlborg wrote:
> Here's my proposal:

Ah yes, I think I did read that before.

I'm not in love with the key=value or the explicit
@attribute on the classes, which is the two biggest
differences we have.

The key=value is nice, but it isn't in the language today,
so it'd be a bunch of special code in the @attribute parser
in the compiler.

If we were to have key=value syntax, I say we should do it
generically (like C style struct initializers?) so it can
work in regular code too, then pick it up naturally here.


I'd prefer to use the existing language syntax in there
so the implementation can literally be as simple as:

if(token == TOKnote) {
   token.next();
   annotations ~= parseExpression();
}


D's existing struct syntax can handle arguments easily
enough with the StructName("member", "member"); style.
Reusing that here keeps the implementation simple,
and it might be more flexible:

enum MyNote = Something("with args", 2);

@note(MyNote) int foo;
@note(MyNote) bool bar;


this would work too with the simple setup, since the
enum is already handled by the compiler's regular code.
Ditto with ctfe, which is an open hook for some potentially
cool stuff down the line without any extra implementation.



The other thing is @attribute struct {} rather than just
struct {}. I don't any benefit to that.  If I want to
reuse a regular, runtime struct to store info at compile
time, why shouldn't I be able to do that?


I'm thinking of @note(X) as meaning simply:

enum tmp = X; // evaluate ctfe, etc
decl.annotations ~= tmp; // store it for later
March 21, 2012
On 3/21/12 10:20 AM, F i L wrote:
> Andrei Alexandrescu wrote:
>> In case there are several non-serialized variables, how do you avoid
>> clashes between different definitions of __nonSerialized?
>
> struct A {
> int a, b;
> mixin NonSerialized!(a, b);
> }
>
> static const __nonSerialized = ["a", "b"];

That's may be a problem because it makes it impossible to put together fields and their non-serializable property.

Ideally the above should work, and also mixing in several NonSerialized instances within the same type should also work.


Andrei

March 21, 2012
On 3/21/12 10:26 AM, F i L wrote:
> On Wednesday, 21 March 2012 at 15:20:35 UTC, F i L wrote:
>> Andrei Alexandrescu wrote:
>>> In case there are several non-serialized variables, how do you avoid
>>> clashes between different definitions of __nonSerialized?
>>
>> struct A {
>> int a, b;
>> mixin NonSerialized!(a, b);
>> }
>>
>> static const __nonSerialized = ["a", "b"];
>
> Also, if where meant how could you store multiple types, you could just
> use an Associative Array:
>
> struct A {
> int a;
> float b;
> mixin NonSerialized!(a, b);
> }
>
> static const __nonSerialized = ["int":"a", "int":"b"];

Is this implemented, or a thought?

Andrei
March 21, 2012
Andrei Alexandrescu wrote:
> Is this implemented, or a thought?

Just a thought (I even accidentally reversed the key-value order), but I don't see why it couldn't work. I'll try and make up a quick implementation.