Jump to page: 1 2
Thread overview
ReturnThis/@chain
Jul 24, 2010
dsimcha
Jul 24, 2010
Eric Poggel
Jul 24, 2010
Nick Sabalausky
Jul 24, 2010
Lutger
Jul 24, 2010
Tomek Sowiński
Jul 24, 2010
Tomek Sowiński
Jul 24, 2010
Fawzi Mohamed
Jul 24, 2010
dsimcha
Jul 24, 2010
Simen kjaeraas
Jul 24, 2010
dsimcha
Jul 24, 2010
Tomek Sowiński
July 24, 2010
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.
July 24, 2010
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.
}
July 24, 2010
"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 :)


July 24, 2010
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.
July 24, 2010
Dnia 24-07-2010 o 04:21:57 dsimcha <dsimcha@yahoo.com> napisał(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 = 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.

This looks like a job for the template this parameter:

    T val(this T)(int newVal) {
        _val = newVal;
        return cast(T) this;
    }

Funny enough, if you put Bar into Foo (Foo bar = new Bar; ) it doesn't work no more.

Tomek
July 24, 2010
Dnia 24-07-2010 o 12:52:51 Tomek Sowiński <just@ask.me> napisał(a):

> Funny enough, if you put Bar into Foo (Foo bar = new Bar; ) it doesn't work no more.

Eh, not funny at all. It doesn't work because it shouldn't (I think).
July 24, 2010
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

July 24, 2010
== 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

NO #$(&$# WAY!!!!!  I (ab)use D metaprogramming constantly and was completely unaware of template this parameters.  This is **exactly** what I needed and I can't believe it's in the language already.
July 24, 2010
On Sat, 24 Jul 2010 16:44:38 +0200, dsimcha <dsimcha@yahoo.com> wrote:

> == 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
>
> NO #$(&$# WAY!!!!!  I (ab)use D metaprogramming constantly and was completely
> unaware of template this parameters.  This is **exactly** what I needed 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
July 24, 2010
== 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
> >
> > NO #$(&$# WAY!!!!!  I (ab)use D metaprogramming constantly and was  =
> > 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.
« First   ‹ Prev
1 2