digitalmars.D - suggestion for eliminating the overload ambiguity for properties
- Bill Baxter (29/29) Jul 29 2007 Right now there's a problem in that if one uses property methods as
- Reiner Pope (42/76) Jul 29 2007 I can see that being able to distinguish setter from getter is
- Kirk McDonald (27/68) Jul 29 2007 [snip]
- Reiner Pope (4/71) Jul 29 2007 Well you know what they say about people with hammers who see nails
- Bill Baxter (4/68) Jul 30 2007 Thanks Reiner and Kirk. Both great tips about how to use current D
Right now there's a problem in that if one uses property methods as suggested by the D reference manual: class Foo { int prop() { ... } int prop(int x) { ... } } then you can't reliably get a delegate to the setter. &aFoo.prop gets you whichever appears first, which in this case is the getter. This is a known bug, and the most likely resolution for it will be to make trying to do this an error. So what if we just give D support for Java-style convention-based deduction of properties. You can keep using properties as-is, but _if_ there's a method called 'set_prop' then it can be used as a setter property. So the above could be written as: class Foo { int prop() { ... } int set_prop(int x) { ... } } This way you can still use your property syntax, but you can also easily distinguish the getter from the setter when taking a delegate. --- Would it be possible to write a __traits-using mixin that scanned the class mixed-into for methods of the form "set_blah" and created a simple wrappers around them like: T blah(T v) { return set_blah(v); } Can a mixin can add members generated on the fly like that? --bb
Jul 29 2007
Bill Baxter wrote:Right now there's a problem in that if one uses property methods as suggested by the D reference manual: class Foo { int prop() { ... } int prop(int x) { ... } } then you can't reliably get a delegate to the setter. &aFoo.prop gets you whichever appears first, which in this case is the getter. This is a known bug, and the most likely resolution for it will be to make trying to do this an error. So what if we just give D support for Java-style convention-based deduction of properties. You can keep using properties as-is, but _if_ there's a method called 'set_prop' then it can be used as a setter property. So the above could be written as: class Foo { int prop() { ... } int set_prop(int x) { ... } } This way you can still use your property syntax, but you can also easily distinguish the getter from the setter when taking a delegate.I can see that being able to distinguish setter from getter is important, and it would be nice not to require casting for that. But I don't think that should be done in the language, because it doesn't generalise to selecting overloads for non-property functions. I thought that you could write a template which gets you the getter/setter using __traits. In fact, I was right, and this turned out to be one of the cleanest uses of traits I've found. I wrote two templates called Getter and Setter, which will return the getter and setter for your particular properties. For instance, if a class Foo has a getter/setter pair, prop, you can write auto f = new Foo(); auto getter = Getter!("prop").fn(f); auto setter = Setter!("prop").fn(f); It's not as nice as &f.prop_set, but I actually think it isn't too bad, over-all.--- Would it be possible to write a __traits-using mixin that scanned the class mixed-into for methods of the form "set_blah" and created a simple wrappers around them like: T blah(T v) { return set_blah(v); } Can a mixin can add members generated on the fly like that?Well.... it doesn't _error_, but I'm not sure what the results mean: template GenCode(T) { pragma(msg, __traits(derivedMembers, T).stringof); static if (__traits(derivedMembers, T).length == 3) const char[] GenCode = "void bar() {}"; else const char[] GenCode = "void bam() {}"; } const char[] Code2 = "void boo() {}"; template TMixin() { void Boom() {} } class Foo { void run() {} mixin TMixin; mixin(Code2); mixin(GenCode!(Foo)); } This compiles, but the pragma outputs ["run","__T6TMixinZ","__T7GenCodeTC14derivedMembers3FooZ"] so it doesn't seem very useful except for members actually declared _in_ the class. -- Reiner
Jul 29 2007
Reiner Pope wrote:Bill Baxter wrote:[snip] Using __traits is not necessary. Pyd has long used this template (though perhaps __traits is cleaner): template property_parts(alias p) { // This may be either the getter or the setter alias typeof(&p) p_t; alias ParameterTypeTuple!(p_t) Info; // This means it's the getter static if (Info.length == 0) { alias p_t getter_type; alias typeof(p(ReturnType!(p_t).init)) function(ReturnType!(p_t)) setter_type; // This means it's the setter } else { alias p_t setter_type; alias Info[0] function() getter_type; } } It is assumed that the setter accepts as an argument the same type which the getter returns. Wrapping this with a prettier interface is left as an exercise for the reader. :-) -- Kirk McDonald http://kirkmcdonald.blogspot.com Pyd: Connecting D and Python http://pyd.dsource.orgRight now there's a problem in that if one uses property methods as suggested by the D reference manual: class Foo { int prop() { ... } int prop(int x) { ... } } then you can't reliably get a delegate to the setter. &aFoo.prop gets you whichever appears first, which in this case is the getter. This is a known bug, and the most likely resolution for it will be to make trying to do this an error. So what if we just give D support for Java-style convention-based deduction of properties. You can keep using properties as-is, but _if_ there's a method called 'set_prop' then it can be used as a setter property. So the above could be written as: class Foo { int prop() { ... } int set_prop(int x) { ... } } This way you can still use your property syntax, but you can also easily distinguish the getter from the setter when taking a delegate.I can see that being able to distinguish setter from getter is important, and it would be nice not to require casting for that. But I don't think that should be done in the language, because it doesn't generalise to selecting overloads for non-property functions. I thought that you could write a template which gets you the getter/setter using __traits. In fact, I was right, and this turned out to be one of the cleanest uses of traits I've found. I wrote two templates called Getter and Setter, which will return the getter and setter for your particular properties. For instance, if a class Foo has a getter/setter pair, prop, you can write
Jul 29 2007
Kirk McDonald wrote:Reiner Pope wrote:Well you know what they say about people with hammers who see nails around them. :-) -- ReinerBill Baxter wrote:[snip] Using __traits is not necessary. Pyd has long used this template (though perhaps __traits is cleaner): template property_parts(alias p) { // This may be either the getter or the setter alias typeof(&p) p_t; alias ParameterTypeTuple!(p_t) Info; // This means it's the getter static if (Info.length == 0) { alias p_t getter_type; alias typeof(p(ReturnType!(p_t).init)) function(ReturnType!(p_t)) setter_type; // This means it's the setter } else { alias p_t setter_type; alias Info[0] function() getter_type; } } It is assumed that the setter accepts as an argument the same type which the getter returns. Wrapping this with a prettier interface is left as an exercise for the reader. :-)Right now there's a problem in that if one uses property methods as suggested by the D reference manual: class Foo { int prop() { ... } int prop(int x) { ... } } then you can't reliably get a delegate to the setter. &aFoo.prop gets you whichever appears first, which in this case is the getter. This is a known bug, and the most likely resolution for it will be to make trying to do this an error. So what if we just give D support for Java-style convention-based deduction of properties. You can keep using properties as-is, but _if_ there's a method called 'set_prop' then it can be used as a setter property. So the above could be written as: class Foo { int prop() { ... } int set_prop(int x) { ... } } This way you can still use your property syntax, but you can also easily distinguish the getter from the setter when taking a delegate.I can see that being able to distinguish setter from getter is important, and it would be nice not to require casting for that. But I don't think that should be done in the language, because it doesn't generalise to selecting overloads for non-property functions. I thought that you could write a template which gets you the getter/setter using __traits. In fact, I was right, and this turned out to be one of the cleanest uses of traits I've found. I wrote two templates called Getter and Setter, which will return the getter and setter for your particular properties. For instance, if a class Foo has a getter/setter pair, prop, you can write
Jul 29 2007
Reiner Pope wrote:Kirk McDonald wrote:Thanks Reiner and Kirk. Both great tips about how to use current D features to disambiguate overloads. --bbReiner Pope wrote:Bill Baxter wrote:[snip] Using __traits is not necessary. Pyd has long used this template (though perhaps __traits is cleaner): template property_parts(alias p) { // This may be either the getter or the setter alias typeof(&p) p_t; alias ParameterTypeTuple!(p_t) Info; // This means it's the getter static if (Info.length == 0) { alias p_t getter_type; alias typeof(p(ReturnType!(p_t).init)) function(ReturnType!(p_t)) setter_type; // This means it's the setter } else { alias p_t setter_type; alias Info[0] function() getter_type; } }Right now there's a problem in that if one uses property methods as suggested by the D reference manual: class Foo { int prop() { ... } int prop(int x) { ... } } then you can't reliably get a delegate to the setter. &aFoo.prop gets you whichever appears first, which in this case is the getter. This is a known bug, and the most likely resolution for it will be to make trying to do this an error. So what if we just give D support for Java-style convention-based deduction of properties. You can keep using properties as-is, but _if_ there's a method called 'set_prop' then it can be used as a setter property. So the above could be written as: class Foo { int prop() { ... } int set_prop(int x) { ... } } This way you can still use your property syntax, but you can also easily distinguish the getter from the setter when taking a delegate.I can see that being able to distinguish setter from getter is important, and it would be nice not to require casting for that. But I don't think that should be done in the language, because it doesn't generalise to selecting overloads for non-property functions. I thought that you could write a template which gets you the getter/setter using __traits. In fact, I was right, and this turned out to be one of the cleanest uses of traits I've found. I wrote two templates called Getter and Setter, which will return the getter and setter for your particular properties. For instance, if a class Foo has a getter/setter pair, prop, you can write
Jul 30 2007