digitalmars.D - suggestion for eliminating the overload ambiguity for properties
- Bill Baxter <dnewsgroup billbaxter.com> Jul 29 2007
- Reiner Pope <some address.com> Jul 29 2007
- Kirk McDonald <kirklin.mcdonald gmail.com> Jul 29 2007
- Reiner Pope <some address.com> Jul 29 2007
- Bill Baxter <dnewsgroup billbaxter.com> Jul 30 2007
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
Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit 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: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
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.org
Jul 29 2007
Kirk McDonald wrote:Reiner Pope wrote: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
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. :-)
Well you know what they say about people with hammers who see nails around them. :-) -- Reiner
Jul 29 2007
Reiner Pope wrote:Kirk McDonald wrote:Reiner Pope wrote: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
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; } }
Thanks Reiner and Kirk. Both great tips about how to use current D features to disambiguate overloads. --bb
Jul 30 2007








Bill Baxter <dnewsgroup billbaxter.com>