Re: Defining some stuff for each class in turn
On Thu, 01 Oct 2009 13:53:46 -0400, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: Jarrett Billingsley wrote: On Thu, Oct 1, 2009 at 12:25 PM, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: [code injection] What do you think? I think it sounds interesting enough, but I can't help but wonder if this is a feature that you've really thought through (especially wrt. how it interacts with mechanisms such as template mixins and normal symbol inheritance), or if you just want it to support some pattern you want to use in Phobos 2. I've known for a long time this was in store if we want to define decent reflection. It's also been a perennial source of trouble with a lot of code that needs to inject members. Let me give another example. When we discussed opCmp around here, people said that's the old way of doing things and that the right way is to use an interface Comparator!T, akin to Java's ComparatorT: http://java.sun.com/j2se/1.5.0/docs/api/java/util/Comparator.html That only solves exactly one level of inheritance. It's a more elaborate solution that doesn't quite help that much. Consider: interface Comparator(T) { int opCmp(T rhs); // yum, exact type } class Widget : Comparator!Widget { override opCmp(Widget rhs) { ... } // yum, exact type } class Gadget : Widget { override opCmp(Gadget rhs) { ... } // ERROR } Of course that didn't work. Gadget.opCmp doesn't override anything. Gadget needs to remember to inherit Comparator!Gadget: class Gadget : Widget, Comparator!Gadget { override opCmp(Gadget rhs) { ... } // oh ok } So any class X in Widget's hierarchy that forgets to inherit Comparator!X undergoes the risk of having the wrong opCmp called for it. With injection, Comparator can be made to work for any interface: interface Comparator(T) { int opCmp(Comparator!T rhs); mixin(Impl) // for each implementation Impl { int opCmp(Impl rhs); override int opCmp(Comparator!T rhs) { return opCmp(cast(Impl) rhs); } } } class Widget : Comparator!Widget { ... } Now every derived class of Widget, including Widget itself, commits to define a opCmp with the proper signature (failure to do so results in a linker error), and also defines the interface function in terms of it. This still isn't optimal. For example, two different derivatives of the same class could try to compare to eachother and end up passing null into your opCmp. It would be nice if the compiler could reject unrelated comparisons: class X: Comparator!X { int opCmp(X) {} } class Y: X { int opCmp(Y) {} } class Z: X { int opCmp(Z) {} } void main() { auto y = new Y; auto z = new Z; z y; // error, rejected because they can't possibly be related } If there was a way to do that it would be cool. I also think the auto-defined opCmp should look like this: override int opCmp(Comparator!T rhs) { if(auto imp = cast(Impl) rhs) return opCmp(imp); return false; } That would cut down on calls into your actual opCmp function with a null argument. -Steve
Re: Defining some stuff for each class in turn
Andrei Alexandrescu wrote: Christopher Wright wrote: Andrei Alexandrescu wrote: I am becoming increasingly aware that we need to provide some means to define certain members (data and functions) for each class as if they were pasted there. Most of the examples given would be well served by decent builtin reflection. Walter thinks reflection is too expensive to be active by default. Find a cheaper way to provide runtime reflection. It's not as sexy as using templates, but it's DRY and easier to use. Slower, but you don't pay the cost of reflection multiple times if you have multiple libraries requiring reflection. What cheaper way would be than allowing a base class to prescribe reflection for its hierarchy? Where do templates even enter the mix? What's slower and why? Why do reflection as a language feature (increases base language size, buggy, rigid) instead of allowing it as a library if we so can? I'm totally against that. Andrei Once you get two or three libraries using reflection, it's cheaper to have the language provide it than to have separate, incompatible reflection systems. It doesn't matter whether the language provides reflection or the standard library. (The only way for me to tell is whether I'm importing from core or from std.) Either way, it should be standardized and easy to opt in or out (depending on the default), and there should be no way or no cost for opting in twice. You have to use templates to get reflection info, currently. Unless CTFE has gotten a lot better, in which case it's effectively the same as using templates, but with a bit less executable bloat. Template-based solutions can be faster than reflection-based solutions because you can access fields and methods directly. But runtime reflection doesn't disallow templates.
Defining some stuff for each class in turn
I am becoming increasingly aware that we need to provide some means to define certain members (data and functions) for each class as if they were pasted there. Right now that right is reserved to the compiler, which generates e.g. one static classinfo object for each class. But users would want to also define members for each class automatically. This is often the case with contravariant-argument functions (that we discussed recently) and other important cases such as factories and cloning. For starters, assume I want to define one static int for each class in a hierarchy. class Counted { static uint counter; ... } Then subclasses of Counted would all share counter, something I don't want. I want each subclass to have its own counter, so I need to ask derived classes to *also* define counter: class A : Counted { static uint counter; ... } With the suggested feature, there would be the ability to define counter for each class in turn. class Counted { mixin(Derived) { // Insert here stuff that must be pasted for each subclass // of Counted (including Counted itself). // Use Derived as the name of the current subtype of Counter static uint counter; static if (is(Counted == Derived)) ref uint getCounter() { return counter; } else override ref uint getCounter() { return counter; } } ... } The code above does something quite neat - it defines an overridable function Counted.getCounter in the base class, and then overrides it in *every* class inheriting that base class, to return that class' own counter. The same should go in interface definitions - the feature should allow you to There are quite a few immediate applications of this: opEquals, opCmp, clone, various factories and object pools, and most importantly reflection. To enable custom reflection with today's D, we'd have to require each class to insert some code inside the class body. With the mechanism described above, we allow the base class or an interface (e.g. Reflectable) to inject the code into the derived class' body. What do you think? Andrei
Re: Defining some stuff for each class in turn
On Thu, Oct 1, 2009 at 12:25 PM, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: I am becoming increasingly aware that we need to provide some means to define certain members (data and functions) for each class as if they were pasted there. Right now that right is reserved to the compiler, which generates e.g. one static classinfo object for each class. But users would want to also define members for each class automatically. This is often the case with contravariant-argument functions (that we discussed recently) and other important cases such as factories and cloning. For starters, assume I want to define one static int for each class in a hierarchy. class Counted { static uint counter; ... } Then subclasses of Counted would all share counter, something I don't want. I want each subclass to have its own counter, so I need to ask derived classes to *also* define counter: class A : Counted { static uint counter; ... } With the suggested feature, there would be the ability to define counter for each class in turn. class Counted { mixin(Derived) { // Insert here stuff that must be pasted for each subclass // of Counted (including Counted itself). // Use Derived as the name of the current subtype of Counter static uint counter; static if (is(Counted == Derived)) ref uint getCounter() { return counter; } else override ref uint getCounter() { return counter; } } ... } The code above does something quite neat - it defines an overridable function Counted.getCounter in the base class, and then overrides it in *every* class inheriting that base class, to return that class' own counter. The same should go in interface definitions - the feature should allow you to There are quite a few immediate applications of this: opEquals, opCmp, clone, various factories and object pools, and most importantly reflection. To enable custom reflection with today's D, we'd have to require each class to insert some code inside the class body. With the mechanism described above, we allow the base class or an interface (e.g. Reflectable) to inject the code into the derived class' body. What do you think? I think it sounds interesting enough, but I can't help but wonder if this is a feature that you've really thought through (especially wrt. how it interacts with mechanisms such as template mixins and normal symbol inheritance), or if you just want it to support some pattern you want to use in Phobos 2.
Re: Defining some stuff for each class in turn
Jarrett Billingsley wrote: On Thu, Oct 1, 2009 at 12:25 PM, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: [code injection] What do you think? I think it sounds interesting enough, but I can't help but wonder if this is a feature that you've really thought through (especially wrt. how it interacts with mechanisms such as template mixins and normal symbol inheritance), or if you just want it to support some pattern you want to use in Phobos 2. I've known for a long time this was in store if we want to define decent reflection. It's also been a perennial source of trouble with a lot of code that needs to inject members. Let me give another example. When we discussed opCmp around here, people said that's the old way of doing things and that the right way is to use an interface Comparator!T, akin to Java's ComparatorT: http://java.sun.com/j2se/1.5.0/docs/api/java/util/Comparator.html That only solves exactly one level of inheritance. It's a more elaborate solution that doesn't quite help that much. Consider: interface Comparator(T) { int opCmp(T rhs); // yum, exact type } class Widget : Comparator!Widget { override opCmp(Widget rhs) { ... } // yum, exact type } class Gadget : Widget { override opCmp(Gadget rhs) { ... } // ERROR } Of course that didn't work. Gadget.opCmp doesn't override anything. Gadget needs to remember to inherit Comparator!Gadget: class Gadget : Widget, Comparator!Gadget { override opCmp(Gadget rhs) { ... } // oh ok } So any class X in Widget's hierarchy that forgets to inherit Comparator!X undergoes the risk of having the wrong opCmp called for it. With injection, Comparator can be made to work for any interface: interface Comparator(T) { int opCmp(Comparator!T rhs); mixin(Impl) // for each implementation Impl { int opCmp(Impl rhs); override int opCmp(Comparator!T rhs) { return opCmp(cast(Impl) rhs); } } } class Widget : Comparator!Widget { ... } Now every derived class of Widget, including Widget itself, commits to define a opCmp with the proper signature (failure to do so results in a linker error), and also defines the interface function in terms of it. Andrei
Re: Defining some stuff for each class in turn
Andrei Alexandrescu wrote: Jarrett Billingsley wrote: I think it sounds interesting enough, but I can't help but wonder if this is a feature that you've really thought through (especially wrt. how it interacts with mechanisms such as template mixins and normal symbol inheritance), or if you just want it to support some pattern you want to use in Phobos 2. I've known for a long time this was in store if we want to define decent reflection. It's also been a perennial source of trouble with a lot of code that needs to inject members. I don't see how that would be needed for reflection, and I've written some custom reflection/serialization myself. Yay for tupleof being able to read even private members.
Re: Defining some stuff for each class in turn
Andrei Alexandrescu, el 1 de octubre a las 11:25 me escribiste: What do you think? I think this is close to Python metaclasses[1], but much more specific. It's amazing how many cool things one can do with Python metaclasses (there are several articles discussing them[2]) and decorators. I would love to see something similar in D but operating at compile-time. I think it would be nice to point to a more general solution (like AST macros) than implementing all sort of small and specific tricks for each problem instead. [1] http://docs.python.org/reference/datamodel.html#customizing-class-creation [2] http://en.wikipedia.org/wiki/Metaclass http://www.ibm.com/developerworks/linux/library/l-pymeta.html -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ -- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) -- Wake from your sleep, the drying of your tears, Today we escape, we escape.
Re: Defining some stuff for each class in turn
On Thu, 01 Oct 2009 20:25:03 +0400, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: I am becoming increasingly aware that we need to provide some means to define certain members (data and functions) for each class as if they were pasted there. Right now that right is reserved to the compiler, which generates e.g. one static classinfo object for each class. But users would want to also define members for each class automatically. This is often the case with contravariant-argument functions (that we discussed recently) and other important cases such as factories and cloning. For starters, assume I want to define one static int for each class in a hierarchy. class Counted { static uint counter; ... } Then subclasses of Counted would all share counter, something I don't want. I want each subclass to have its own counter, so I need to ask derived classes to *also* define counter: class A : Counted { static uint counter; ... } With the suggested feature, there would be the ability to define counter for each class in turn. class Counted { mixin(Derived) { // Insert here stuff that must be pasted for each subclass // of Counted (including Counted itself). // Use Derived as the name of the current subtype of Counter static uint counter; static if (is(Counted == Derived)) ref uint getCounter() { return counter; } else override ref uint getCounter() { return counter; } } ... } The code above does something quite neat - it defines an overridable function Counted.getCounter in the base class, and then overrides it in *every* class inheriting that base class, to return that class' own counter. The same should go in interface definitions - the feature should allow you to There are quite a few immediate applications of this: opEquals, opCmp, clone, various factories and object pools, and most importantly reflection. To enable custom reflection with today's D, we'd have to require each class to insert some code inside the class body. With the mechanism described above, we allow the base class or an interface (e.g. Reflectable) to inject the code into the derived class' body. What do you think? Andrei This is cool. I'd also add Serialization task to the application list (currently I manually insert mixin Serializable!(); into every class. There is one thing that I dislike about it, though. I believe mixin(Foo) {} syntax is a bit far-fetched, it is not obvious that Foo represents derived type inside a mixin scope. I'd like to remind you that we could just use typeof(this) instead of Foo/Derived/etc: static if (is (typeof(this) == Counted) { ref uint getCounter() { return counter; } } else { override ref uint getCounter() { return counter; } } If you remember, we had a similar discussion about a half year ago. It was about ICloneable interface that forces all derived class to implement proper clone() method. We could define it as: // forces implementor class and all the derivatives to implement proper clone() method interface ICloneable { scope mixin { // alternative syntax typeof(this) clone(); } } and also be able to declare a method non-recursively (so that derived class don't have to implement that method): interface ICloneableNonRecursive { typeof(this) clone(); } Other possible solution could be to use a special derived keyword. We already have a class-level compile-time constant - super. We could also introduce its counter-part (derived), which will expand into a concrete derived class type. This will simplify the syntax a bit and will allow to get rid of mixin and an addition level of indentation: interface ICloneable { derived clone(); } interface IComparable { int opCmp(derived other); } As a downside, I don't know how to define a field in every class this way (int derived.counter; maybe?).
Re: Defining some stuff for each class in turn
Denis Koroskin wrote: On Thu, 01 Oct 2009 20:25:03 +0400, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: [...] What do you think? Andrei This is cool. I'd also add Serialization task to the application list (currently I manually insert mixin Serializable!(); into every class. Yah, serialization is close to reflection so it's definitely part of the target applications of the features. There is one thing that I dislike about it, though. I believe mixin(Foo) {} syntax is a bit far-fetched, it is not obvious that Foo represents derived type inside a mixin scope. I'd like to remind you that we could just use typeof(this) instead of Foo/Derived/etc: static if (is (typeof(this) == Counted) { ref uint getCounter() { return counter; } } else { override ref uint getCounter() { return counter; } } Yah, I thought a lot along the likes of typeof(this). We need some symbolic alias for the struct or class currently being defined and typeof(this) is an obvious choice. I just fear that it might be confusing that typeof(this) works even outside any method, i.e. when there is no this. If you remember, we had a similar discussion about a half year ago. It was about ICloneable interface that forces all derived class to implement proper clone() method. We could define it as: // forces implementor class and all the derivatives to implement proper clone() method interface ICloneable { scope mixin {// alternative syntax typeof(this) clone(); } } Yah, I remember. and also be able to declare a method non-recursively (so that derived class don't have to implement that method): interface ICloneableNonRecursive { typeof(this) clone(); } Other possible solution could be to use a special derived keyword. We already have a class-level compile-time constant - super. We could also introduce its counter-part (derived), which will expand into a concrete derived class type. This will simplify the syntax a bit and will allow to get rid of mixin and an addition level of indentation: interface ICloneable { derived clone(); } interface IComparable { int opCmp(derived other); } As a downside, I don't know how to define a field in every class this way (int derived.counter; maybe?). I dislike adding yet another keyword. In fact, I want to propose Walter to eliminate super as a keyword and make it just an alias for the base class as if you defined it by hand. Andrei
Re: Defining some stuff for each class in turn
On Thu, 01 Oct 2009 12:53:46 -0500, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: interface Comparator(T) { int opCmp(Comparator!T rhs); mixin(Impl) // for each implementation Impl { int opCmp(Impl rhs); override int opCmp(Comparator!T rhs) { return opCmp(cast(Impl) rhs); } } } I like that you can use this in interfaces too. It seems to allow for something similar to multiple inheritance, but presumably without the implementation difficulty. Phil Deets
Re: Defining some stuff for each class in turn
Phil Deets wrote: On Thu, 01 Oct 2009 12:53:46 -0500, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: interface Comparator(T) { int opCmp(Comparator!T rhs); mixin(Impl) // for each implementation Impl { int opCmp(Impl rhs); override int opCmp(Comparator!T rhs) { return opCmp(cast(Impl) rhs); } } } I like that you can use this in interfaces too. It seems to allow for something similar to multiple inheritance, but presumably without the implementation difficulty. Phil Deets That's a great point. To compare this feature with Scala's mixins (which I studied and now feel are a good feature), my understanding is that Scala mixins are an interface plus a default implementation. The feature proposed above is an interface with a prescribed implementation. That way, Scala mixins seem to be somewhat more flexible. Andrei
Re: Defining some stuff for each class in turn
Andrei Alexandrescu wrote: I am becoming increasingly aware that we need to provide some means to define certain members (data and functions) for each class as if they were pasted there. Most of the examples given would be well served by decent builtin reflection. Walter thinks reflection is too expensive to be active by default. Find a cheaper way to provide runtime reflection. It's not as sexy as using templates, but it's DRY and easier to use. Slower, but you don't pay the cost of reflection multiple times if you have multiple libraries requiring reflection.
Re: Defining some stuff for each class in turn
Christopher Wright wrote: Andrei Alexandrescu wrote: I am becoming increasingly aware that we need to provide some means to define certain members (data and functions) for each class as if they were pasted there. Most of the examples given would be well served by decent builtin reflection. Walter thinks reflection is too expensive to be active by default. Find a cheaper way to provide runtime reflection. It's not as sexy as using templates, but it's DRY and easier to use. Slower, but you don't pay the cost of reflection multiple times if you have multiple libraries requiring reflection. What cheaper way would be than allowing a base class to prescribe reflection for its hierarchy? Where do templates even enter the mix? What's slower and why? Why do reflection as a language feature (increases base language size, buggy, rigid) instead of allowing it as a library if we so can? I'm totally against that. Andrei
Re: Defining some stuff for each class in turn
On 2009-10-01 14:05:10 -0400, Max Samukha spam...@d-coding.com said: For example, the upcoming reflection mechanism in QtD (which uses its own metaobjects instead of the limited classinfo) requires manual insertion of a mixin into derived classes unless the mixin is inserted implicitly when a signal/property/etc is declared. I'm using the exact same solution here for the D/Objective-C bridge and it's working surprisingly well. I certainly wouldn't turn down the possibility of inheriting an implementation in subclasses, it'd make things a little less hackish. -- Michel Fortin michel.for...@michelf.com http://michelf.com/