www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - suggestion for eliminating the overload ambiguity for properties

reply Bill Baxter <dnewsgroup billbaxter.com> writes:
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
parent reply Reiner Pope <some address.com> writes:
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
parent reply Kirk McDonald <kirklin.mcdonald gmail.com> writes:
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
[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.org
Jul 29 2007
parent reply Reiner Pope <some address.com> writes:
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
[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. :-)
Well you know what they say about people with hammers who see nails around them. :-) -- Reiner
Jul 29 2007
parent Bill Baxter <dnewsgroup billbaxter.com> writes:
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
[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; } }
Thanks Reiner and Kirk. Both great tips about how to use current D features to disambiguate overloads. --bb
Jul 30 2007