The object operator

Timon Gehr via Digitalmars-d digitalmars-d at puremagic.com
Fri Aug 14 07:20:56 PDT 2015


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);
}



More information about the Digitalmars-d mailing list