www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - ReturnThis/ chain

reply dsimcha <dsimcha yahoo.com> writes:
I'm working on the next iteration of my Plot2Kill library, and I **really**
have fallen in love with property chaining.  It's the greatest thing since
sliced arrays.  However, I've run into an issue that I had previously
overlooked:

class Foo {
    Type _val;

    typeof(this) val(Type newVal) {
        _val = newVal;
        return this;
    }
}

class Bar : Foo {
    // More properties.
}

void main() {
    auto bar = new Bar;
    bar.val(someValue).barProperty(someOtherValue);  // Won't work.
}

Given that D2 is mostly finalized, it may be a little late for this, but would
it be feasible, at least far down the road, to add something like an  chain
annotation, which would only allow a member function to return this and would
implicitly downcast it to the subtype that was passed in as the this pointer?
 For example, assume we attached  chain to Foo.val():

pragma(msg, typeof(bar.val(someValue)));  // Bar, not Foo.
Jul 23 2010
next sibling parent Eric Poggel <dnewsgroup yage3d.net> writes:
On 7/23/2010 10:21 PM, dsimcha wrote:
 class Foo {
      Type _val;

      typeof(this) val(Type newVal) {
          _val = newVal;
          return this;
      }
 }

 class Bar : Foo {
      // More properties.
 }

 void main() {
      auto bar = new Bar;
      bar.val(someValue).barProperty(someOtherValue);  // Won't work.
 }
What about using templates? I haven't tested this code but it seems like I've accomplished something similar before. class Foo(T=Foo) { Type _val; T val(Type newVal) { _val = newVal; return this; } } class Bar : Foo!(Bar) { // More properties. }
Jul 23 2010
prev sibling next sibling parent "Nick Sabalausky" <a a.a> writes:
"dsimcha" <dsimcha yahoo.com> wrote in message 
news:i2dio5$25mi$1 digitalmars.com...
 It's the greatest thing since sliced arrays.
That's the greatest quote since...well, I can't top that one, so I'm not going to try :)
Jul 23 2010
prev sibling next sibling parent Lutger <lutger.blijdestijn gmail.com> writes:
dsimcha wrote:

 I'm working on the next iteration of my Plot2Kill library, and I **really**
 have fallen in love with property chaining.  It's the greatest thing since
 sliced arrays.  However, I've run into an issue that I had previously
 overlooked:
 
 class Foo {
     Type _val;
 
     typeof(this) val(Type newVal) {
         _val = newVal;
         return this;
     }
 }
 
 class Bar : Foo {
     // More properties.
 }
 
 void main() {
     auto bar = new Bar;
     bar.val(someValue).barProperty(someOtherValue);  // Won't work.
 }
 
 Given that D2 is mostly finalized, it may be a little late for this, but would
 it be feasible, at least far down the road, to add something like an  chain
 annotation, which would only allow a member function to return this and would
 implicitly downcast it to the subtype that was passed in as the this pointer?
  For example, assume we attached  chain to Foo.val():
 
 pragma(msg, typeof(bar.val(someValue)));  // Bar, not Foo.
Why not use covariance? Or is that too much boilerplate? this will work: class Bar : Foo { override typeof(this) val(Type newVal) { return super(newVal); } } This could be automated with a mixin.
Jul 24 2010
prev sibling parent reply =?iso-8859-2?B?VG9tZWsgU293afFza2k=?= <just ask.me> writes:
Dnia 24-07-2010 o 04:21:57 dsimcha <dsimcha yahoo.com> napisa=B3(a):

 I'm working on the next iteration of my Plot2Kill library, and I  =
 **really**
 have fallen in love with property chaining.  It's the greatest thing  =
 since
 sliced arrays.  However, I've run into an issue that I had previously =
=
 overlooked:

 class Foo {
     Type _val;

     typeof(this) val(Type newVal) {
         _val =3D newVal;
         return this;
     }
 }

 class Bar : Foo {
     // More properties.
 }

 void main() {
     auto bar =3D new Bar;
     bar.val(someValue).barProperty(someOtherValue);  // Won't work.
 }

 Given that D2 is mostly finalized, it may be a little late for this, b=
ut =
 would
 it be feasible, at least far down the road, to add something like an  =
  chain
 annotation, which would only allow a member function to return this an=
d =
 would
 implicitly downcast it to the subtype that was passed in as the this  =
 pointer?
  For example, assume we attached  chain to Foo.val():

 pragma(msg, typeof(bar.val(someValue)));  // Bar, not Foo.
This looks like a job for the template this parameter: T val(this T)(int newVal) { _val =3D newVal; return cast(T) this; } Funny enough, if you put Bar into Foo (Foo bar =3D new Bar; ) it doesn't= = work no more. Tomek
Jul 24 2010
next sibling parent =?iso-8859-2?B?VG9tZWsgU293afFza2k=?= <just ask.me> writes:
Dnia 24-07-2010 o 12:52:51 Tomek Sowi=F1ski <just ask.me> napisa=B3(a):

 Funny enough, if you put Bar into Foo (Foo bar =3D new Bar; ) it doesn=
't =
 work no more.
Eh, not funny at all. It doesn't work because it shouldn't (I think).
Jul 24 2010
prev sibling next sibling parent Fawzi Mohamed <fawzi gmx.ch> writes:
I also found chaining more cumbersome than it should be, and made a  
bug report
	http://d.puremagic.com/issues/show_bug.cgi?id=2295
and it turned out I wasn't the first thinking along those lines, as
	http://d.puremagic.com/issues/show_bug.cgi?id=1835
shows.

Maybe it is time to revisit the proposal?

In the meantime for example for i/o in blip I created a templated  
Dumper object that does call chaining (only with opCall, but in D2  
with opDot one could do it for basically all methods...

see
	http://github.com/fawzi/blip/blob/master/blip/io/BasicIO.d#L505
for a D1 example

using the helper function then I simply do

dumper(s)(bla)(bla)(bla);

:)

one has to be a bit careful if the s object is a struct or any non ref  
object, as call chaining would modify the copies, so I have some  
checks for that.

Fawzi
Jul 24 2010
prev sibling parent reply dsimcha <dsimcha yahoo.com> writes:
== Quote from Tomek Sowiński (just ask.me)'s article
 pragma(msg, typeof(bar.val(someValue)));  // Bar, not Foo.
This looks like a job for the template this parameter: T val(this T)(int newVal) { _val =3D newVal; return cast(T) this; } Funny enough, if you put Bar into Foo (Foo bar =3D new Bar; ) it doesn't= = work no more. Tomek
unaware of template this parameters. This is **exactly** what I needed and I can't believe it's in the language already.
Jul 24 2010
parent reply "Simen kjaeraas" <simen.kjaras gmail.com> writes:
On Sat, 24 Jul 2010 16:44:38 +0200, dsimcha <dsimcha yahoo.com> wrote:

 =3D=3D Quote from Tomek Sowi=C5=84ski (just ask.me)'s article
 pragma(msg, typeof(bar.val(someValue)));  // Bar, not Foo.
This looks like a job for the template this parameter: T val(this T)(int newVal) { _val =3D3D newVal; return cast(T) this; } Funny enough, if you put Bar into Foo (Foo bar =3D3D new Bar; ) it =
 doesn't=3D
   =3D
 work no more.
 Tomek
 completely
 unaware of template this parameters.  This is **exactly** what I neede=
d =
 and I
 can't believe it's in the language already.
What, this is seriously already here? Why the fuck was I not informed? Seriously, this is one under-advertised feature. -- = Simen
Jul 24 2010
parent reply dsimcha <dsimcha yahoo.com> writes:
== Quote from Simen kjaeraas (simen.kjaras gmail.com)'s article
 On Sat, 24 Jul 2010 16:44:38 +0200, dsimcha <dsimcha yahoo.com> wrote:
 =3D=3D Quote from Tomek Sowi=C5=84ski (just ask.me)'s article
 pragma(msg, typeof(bar.val(someValue)));  // Bar, not Foo.
This looks like a job for the template this parameter: T val(this T)(int newVal) { _val =3D3D newVal; return cast(T) this; } Funny enough, if you put Bar into Foo (Foo bar =3D3D new Bar; ) it = doesn't=3D =3D work no more. Tomek
completely unaware of template this parameters. This is **exactly** what I neede=
d =
 and I
 can't believe it's in the language already.
What, this is seriously already here? Why the fuck was I not informed? Seriously, this is one under-advertised feature. -- = Simen
...but on attempting to use it, it's rather useless in cases where you also want to provide a getter because: 1. You can't overload functions against templates, even in situations where this would be completely unambiguous (see bug 2972 http://d.puremagic.com/issues/show_bug.cgi?id=2972). 2. If you make your getter also have a template this parameter, it doesn't work because your getter isn't returning this.
Jul 24 2010
parent Tomek =?UTF-8?B?U293acWEc2tp?= <just ask.me> writes:
dsimcha wrote:

 ...but on attempting to use it, it's rather useless in cases where you
 also want to provide a getter because:
 
 1.  You can't overload functions against templates, even in situations
 where this would be completely unambiguous (see bug 2972
 http://d.puremagic.com/issues/show_bug.cgi?id=2972).
 
 2.  If you make your getter also have a template this parameter, it
 doesn't work because your getter isn't returning this.
Hm.. getters.. I don't get it;) What are you trying to pull off with them (example)? Tomek
Jul 24 2010