| Thread overview | |||||||
|---|---|---|---|---|---|---|---|
|
August 14, 2015 The object operator | ||||
|---|---|---|---|---|
| ||||
For class types, a special operator is defined to return the class object for method calls rather than the return value from the call itself. The use of the operator places the return types in special variables to be accessed easily. The operator is simply a syntax helper and is along the lines of UFCS.
e.g.,
class myClass
{
Do(int x) { return x + 2; }
}
auto myObj = new myClass();
assert(@@myObj.Do(3).Do(4).Do(5) == 7);
Of course, such a silly example is not very helpful but demonstrates the concept.
To make such a syntax work well, I believe one then needs a further operator to access the last return value.
e.g.,
assert(@@myObj.Do(3).Do(@).Do(@2) == 9);
Where the same symbol is used for there return value placeholders and indices are used to access nested calls return value with @ defaulting to @1.
Essentially such syntax allows for easily doing nested calls.
The only down side is that the operator could only be used on one method call at a type in the nesting. (or multiple or parameritized operators would be required)
Obviously @ would not be the symbol of choice.
| ||||
August 14, 2015 Re: The object operator | ||||
|---|---|---|---|---|
| ||||
Posted in reply to TheHamster | On Friday, 14 August 2015 at 04:17:25 UTC, TheHamster wrote:
>
> assert(@@myObj.Do(3).Do(@).Do(@2) == 9);
>
If what you want is to omit the object during the call chain, you can use with statement to mimic this feature, though not as compact as you suggested:
```
import std.stdio;
class MyClass {
int run(int x) { return x + 2; }
}
void main() {
auto ob = new MyClass();
int res;
with (ob) {
run(3);
run(4);
run(5);
}
}
```
| |||
August 14, 2015 Re: The object operator | ||||
|---|---|---|---|---|
| ||||
Posted in reply to TheHamster | On Friday, 14 August 2015 at 04:17:25 UTC, TheHamster wrote: > For class types, a special operator is defined to return the class object for method calls rather than the return value from the call itself. The use of the operator places the return types in special variables to be accessed easily. The operator is simply a syntax helper and is along the lines of UFCS. > > e.g., > > class myClass > { > Do(int x) { return x + 2; } > > } > > auto myObj = new myClass(); > assert(@@myObj.Do(3).Do(4).Do(5) == 7); > > Of course, such a silly example is not very helpful but demonstrates the concept. > > To make such a syntax work well, I believe one then needs a further operator to access the last return value. > > e.g., > > assert(@@myObj.Do(3).Do(@).Do(@2) == 9); > > Where the same symbol is used for there return value placeholders and indices are used to access nested calls return value with @ defaulting to @1. > > Essentially such syntax allows for easily doing nested calls. > > The only down side is that the operator could only be used on one method call at a type in the nesting. (or multiple or parameritized operators would be required) > > Obviously @ would not be the symbol of choice. Actually you can already do that by encapsulating a field an playing with a property setter that also return `this`: --- class Foo { private int _field; Foo bar(int x) {_field += x + 2; return this;} int bar(){return _field;} } void main(string[] args) { auto foo = new Foo; // same as assert(@@myObj.Do(3).Do(@).Do(@2) == 9); assert(foo.bar(3).bar(foo.bar).bar(foo.bar).bar == 9); auto f = new Foo; // same as assert(@@myObj.Do(3).Do(@).Do(@2) == 9); with(f) {assert(bar(3).bar(bar).bar(bar).bar == 9);} } --- | |||
August 14, 2015 Re: The object operator | ||||
|---|---|---|---|---|
| ||||
Posted in reply to TheHamster | On 08/14/2015 06:17 AM, TheHamster wrote: > For class types, a special operator is defined to return the class > object for method calls rather than the return value from the call > itself. The use of the operator places the return types in special > variables to be accessed easily. The operator is simply a syntax helper > and is along the lines of UFCS. > > e.g., > > class myClass > { > Do(int x) { return x + 2; } > > } > > auto myObj = new myClass(); > assert(@@myObj.Do(3).Do(4).Do(5) == 7); > > Of course, such a silly example is not very helpful but demonstrates the > concept. > > To make such a syntax work well, I believe one then needs a further > operator to access the last return value. > > e.g., > > assert(@@myObj.Do(3).Do(@).Do(@2) == 9); > > Where the same symbol is used for there return value placeholders and > indices are used to access nested calls return value with @ defaulting > to @1. > > Essentially such syntax allows for easily doing nested calls. > > The only down side is that the operator could only be used on one method > call at a type in the nesting. (or multiple or parameritized operators > would be required) > > Obviously @ would not be the symbol of choice. > > Close enough? :o) import std.typecons; // (workaround for lack of seq return) class MyClass{ int do_(int x){ return x+2; } } void main(){ auto myObj=new MyClass(); assert(op(myObj).do_(3).do_(4).do_(5).val==7); assert(op(myObj).do_(3).do_[$[0]].do_[$[1]].val==9); } alias Seq(T...)=T; struct Op(T,S...){ T wrap; S vals; static if(vals.length) alias val=vals[$-1]; template opDispatch(string s){ auto opDispatch(A...)(A args){ static struct Wrap{ Op* outer; // (workaround) auto opCall(B...)(B args){ static if(is(typeof(mixin(`outer.wrap.`~s)(args))==void)){ mixin(`outer.wrap.`~s)(args); return Op!(T,S,void[0])(outer.wrap,outer.vals,[]); }else{ auto cur=mixin(`outer.wrap.`~s)(args); return Op!(T,S,typeof(cur))(outer.wrap,outer.vals,cur); } } auto opIndex(T...)(T args){ return opCall(args); } @property opDollar(){ return tuple(outer.vals); } } Wrap w; w.outer=&this; static if(args.length) return w(args); else return w; } } } auto op(T)(T t){ return Op!T(t); } | |||
August 14, 2015 Re: The object operator | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | On Friday, 14 August 2015 at 14:20:57 UTC, Timon Gehr wrote:
> On 08/14/2015 06:17 AM, TheHamster wrote:
>>[...]
>
> Close enough? :o)
>
> import std.typecons; // (workaround for lack of seq return)
>
> [...]
Cool, I guess it is about as close as you can get in D with compiler support. Is $ a good choice in D? It seems like it might, in some cases be a bad choice(since it is used for slicing and such)?
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply