Re: Setter chaining

2018-05-30 Thread DigitalDesigns via Digitalmars-d-learn

The above idea can be emulated in code, abiet ugly and useless:

https://dpaste.dzfl.pl/bd118bc1910c




import std.stdio;

struct CT(A,B)
{
A v;
B t;
alias v this;

B opUnary(string s)() if (s == "~")
{
return t;
}

A opUnary(string s)() if (s == "*")
{
return v;
}

}


class C
{
int q;
	CT!(int, typeof(this)) foo() { q = 3; CT!(int, typeof(this)) v; 
v.t = this; v.v = q; return v; }
	CT!(int, typeof(this)) bar(int y) { q = q + y; CT!(int, 
typeof(this)) v; v.t = this; v.v = q; return v; }

}


void main()
{
C c = new C();

auto x = *((~c.foo()).bar(6));



writeln(x);
}

With a language implementation, all one would need is a symbol, 
using #,


everything would simplify to


class C
{
int q;
int foo() { q = 3; return q; }
int bar(int y) { q = q + y; return q;}
}

auto x = c.#foo().bar(6);






Re: Setter chaining

2018-05-30 Thread DigitalDesigns via Digitalmars-d-learn
On Wednesday, 30 May 2018 at 15:46:36 UTC, Steven Schveighoffer 
wrote:

On 5/30/18 10:49 AM, DigitalDesigns wrote:

Does it sound good?

class X
{
    double x;
    @property X foo(double y) { x = y; return this; }

    @property X bar(double y) { x = y + 5; return this; }
}

void main()
{
 X x = new X();
 x.foo(3).bar(4);
}


It sort of emulates UFCS but I'm not sure if it's more trouble 
than it's worth.



I figure it would be better than just returning void as it 
provides the option to chain but not sure if it will come back 
to bite me.


Yes, I do this kind of stuff, but you need to word your 
functions correctly.


I would avoid @property there, as this implies you should use 
it like:


x.foo = 5;

and if you return a reference to the type itself, it will read 
weird if you do it that way:


auto five = (x.foo = 5);

Here the name of the function is really really important.

In my use case, I am kind of using it in an SQL builder type, 
where each time you call a method it adds some piece of the 
query. Like:


auto query = table.select("id, name").where("foo = 
5").orderBy("name");


-Steve


Well, what I mean is to be able to have the ability to assign 
like a field or a function.



sometimes I might want to use it as a property like

x.foo = 5;

and sometimes like a method

x.foo(5).foo(8);

for chaining.

Rather than having to to create setfoo and such.

Since D allows both syntaxes to be used, rather than returning 
void, turning parenting object allows the chaining to take place.


Since the trick here is to be consistent, all setters must follow 
this principle, it shouldn't be a problem with consistency.




auto five = (x.foo = 5);


I wouldn't do that,just doesn't look right but I see your point.

What would be cool is if D had some special way to return the 
object of the class the setter was in.


auto x = (@x.foo = 5);

Here @ returns x but first computes x.foo = 5;.

In a way, it is like "this". @ gets the "this" of the function. 
Could work on any function:


class Y
{
   void foo();
   @property int baz();
   @property double bar(int x);
}

y.@foo() returns y;
y.@baz() returns y;
y.@bar(3) returns y;

Essentially one could few all functions as returning this and the 
value in a tuple and be default the value is returned and using a 
"selector" character will return this.


class Y
{
   Tuple!(void, typeof(this)) foo();
   Tuple!(int, typeof(this)) baz();
   Tuple!(double, typeof(this)) bar(int x);
}

y.foo()[1] returns y;
...

The compiler could simplify all this and by putting this in a 
register it could be be quite fast. In fact, since these are 
member functions and this is passed it will just fall through so 
very little overhead. The compiler can also optimize the code. 
Might take a bit to verify all the corner cases but would 
probably be useful once people could use it and get used to it.


@, $, |, ?, ! or many symbols could be used without ambiguity 
because a dot will always preceded them.











Re: Setter chaining

2018-05-30 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/30/18 10:49 AM, DigitalDesigns wrote:

Does it sound good?

class X
{
    double x;
    @property X foo(double y) { x = y; return this; }

    @property X bar(double y) { x = y + 5; return this; }
}

void main()
{
 X x = new X();
 x.foo(3).bar(4);
}


It sort of emulates UFCS but I'm not sure if it's more trouble than it's 
worth.



I figure it would be better than just returning void as it provides the 
option to chain but not sure if it will come back to bite me.


Yes, I do this kind of stuff, but you need to word your functions correctly.

I would avoid @property there, as this implies you should use it like:

x.foo = 5;

and if you return a reference to the type itself, it will read weird if 
you do it that way:


auto five = (x.foo = 5);

Here the name of the function is really really important.

In my use case, I am kind of using it in an SQL builder type, where each 
time you call a method it adds some piece of the query. Like:


auto query = table.select("id, name").where("foo = 5").orderBy("name");

-Steve


Setter chaining

2018-05-30 Thread DigitalDesigns via Digitalmars-d-learn

Does it sound good?

class X
{
   double x;
   @property X foo(double y) { x = y; return this; }

   @property X bar(double y) { x = y + 5; return this; }
}

void main()
{
X x = new X();
x.foo(3).bar(4);
}


It sort of emulates UFCS but I'm not sure if it's more trouble 
than it's worth.



I figure it would be better than just returning void as it 
provides the option to chain but not sure if it will come back to 
bite me.