www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - std.v2 builder pattern replacement

reply monkyyy <crazymonkyyy gmail.com> writes:
So today I was looking into builder patterns with opDispatch, 
complained about d's edge cases; throw out some ideas that snar 
told me instantly wouldn't work etc. etc.

Anyway, the conclusion of this discussion is an idea for a 
pattern.

```d
auto withMe(string mixin_,Me,T...)(Me me,T arg){
	with(me){
		mixin(mixin_);
	}
	import std.algorithm;
	static if(!mixin_.canFind("return")){
		return me;
	}
}
auto withRefMe(string mixin_,Me,T...)(ref Me me,T arg){
	with(me){
		mixin(mixin_);
	}
	import std.algorithm;
	static if(!mixin_.canFind("return")){
		return me;
	}
}

struct complextype{
	bool isfoo,isbar,isfoobar;
	int i;
	float f;
	bool b;
}
struct point{
	int x,y,xv,yv;
}
alias atZero=withMe!(q{return x==0 && y==0;},point);
void main(){
	import std.stdio;
	auto p=point(1,2,3,4);
	p.withRefMe!q{x=xv;y=yv;};//update a simple object
	p.writeln;
	p.atZero.writeln;
	p.withRefMe!q{x=0;y=0;};
	p.atZero.writeln;
	auto foo=complextype().withMe!q{
		isfoo=true;
		i=1337;
	}();
	auto bar=complextype().withMe!q{
		isbar=true;
		f=4.20;
	};
	auto foobar=complextype().withMe!q{
		isfoobar=true;
		b=true;
	};
	writeln(foo);
	writeln(bar);
	writeln(foobar);
}
```

At this moment I don't know how to have this compile ref and non 
ref at the same time.

But I suggest something like this gets into std.v2 and everyone 
uses it rather than rolling a custom builder in the future
Jul 22 2022
next sibling parent reply ryuukk_ <ryuukk.dev gmail.com> writes:
I feel like you are over complicating and over engineering it, 
and builder pattern is overrated imo

If we had (designated inits everywhere) 
https://forum.dlang.org/thread/bcfhuxjqppthigqppyid forum.dlang.org

We could simply use the struct, with defaults, and that is it, 
compiler will optimize everything anyways, you got your better 
builder

I personally never been a fan of using templates for the sake of 
using templates when the simple solution is at our hands, it 
makes the code harder to read, harder to write and it adds up to 
making your program slow to compile

https://twitter.com/flohofwoe/status/1068589642767900672
Jul 22 2022
parent reply monkyyy <crazymonkyyy gmail.com> writes:
On Friday, 22 July 2022 at 21:00:49 UTC, ryuukk_ wrote:
 I feel like you are over complicating and over engineering it, 
 and builder pattern is overrated imo
 to making your program slow to compile
Fundmentally its ufcs-able with statement And this isnt going to be a slow template
Jul 22 2022
parent ryuukk_ <ryuukk.dev gmail.com> writes:
On Friday, 22 July 2022 at 23:19:53 UTC, monkyyy wrote:
 On Friday, 22 July 2022 at 21:00:49 UTC, ryuukk_ wrote:
 I feel like you are over complicating and over engineering it, 
 and builder pattern is overrated imo
 to making your program slow to compile
Fundmentally its ufcs-able with statement And this isnt going to be a slow template
It's stacks up, then it becomes a problem as you watch your build speed tank as you import things from `std`, wich is already in a bad spot imo I personally think the `std` should only focus on 4 core APIs - memory (allocators) - containers (datastructures) - i/o (networking, event loop, database driver) - filesystem (files/path) Anything else is maintenance burden When you pick up a language and look at using the `std` you don't search for build pattern templates, you check if it has networking stuff to write your app, and that's where Phobos is lacking and failing behind Builder pattern is local to your program That is why all these sumtype/nullable etc should not be in the std and should be builtins instead
Jul 23 2022
prev sibling next sibling parent Salih Dincer <salihdb hotmail.com> writes:
On Friday, 22 July 2022 at 19:06:05 UTC, monkyyy wrote:
 So today I was looking into builder patterns with opDispatch, 
 complained about d's edge cases; throw out some ideas that snar 
 told me instantly wouldn't work etc. etc.

 Anyway, the conclusion of this discussion is an idea for a 
 pattern.

 ```d
   auto withMe(string mixin_,Me,T...)(Me me,T arg){
 	with(me){
 		mixin(mixin_);
 	}
 	import std.algorithm;
 	static if(!mixin_.canFind("return")){
 		return me;
 	}
   }
   auto foo=complextype().withMe!q{
     isfoo=true;
     i=1337;
   }();
 ```
This convenience function looks very useful. However, when I try, initA and initB give the same result. Moreover, the classic C-style is much shorter and similar: ```d import std.stdio; struct Harf { char harf = 96; string toString() { return [harf]; } } enum { A = 97, B, C, D } enum a = Harf(A); enum b = Harf(B); auto withMe(string elements, Me, T...)(Me me, T arg){ with(me) mixin(elements); return me; } void main() { struct S { Harf[] hler; int[] nler; int n; } /* toggleCode: auto initA = S().withMe!q{ hler = [a, b]; nler = [1, 2]; n = 3; }; initA.writeln; /*/ S initB = { hler : [a, b], nler : [1, 2], n : 3 }; initB.writeln; //*/ } /* Prints: S([a, b], [1, 2], 3) */ ``` Respects... SDB 79
Jul 23 2022
prev sibling parent reply FeepingCreature <feepingcreature gmail.com> writes:
On Friday, 22 July 2022 at 19:06:05 UTC, monkyyy wrote:
 So today I was looking into builder patterns with opDispatch, 
 complained about d's edge cases; throw out some ideas that snar 
 told me instantly wouldn't work etc. etc.

 Anyway, the conclusion of this discussion is an idea for a 
 pattern.

 ```d
       ...
 	auto foo=complextype().withMe!q{
 		isfoo=true;
 		i=1337;
 	}();
       ...
 ```

 At this moment I don't know how to have this compile ref and 
 non ref at the same time.

 But I suggest something like this gets into std.v2 and everyone 
 uses it rather than rolling a custom builder in the future
This only works with constants; it cannot function when assigning variables from the callsite. You'd need something horrible like ```d int callerI = 1337; auto foo = mixin(complextype().withMe!q{ i = callerI; }); ``` This is what we use on our end: ```d import boilerplate; struct Test { bool isfoo; int i; mixin(GenerateThis); } ... void main() { int callerI = 1337; Test foo() { with (Test.Builder()) { isfoo = true; i = callerI; return value; } } } ``` It's not exactly compact, but it's the best I think can be done before named arguments.
Jul 27 2022
parent monkyyy <crazymonkyyy gmail.com> writes:
On Wednesday, 27 July 2022 at 09:15:28 UTC, FeepingCreature wrote:
 This only works with constants;
```d auto withMe(string mixin_,Me,T...)(Me me,T arg){ with(me){ mixin(mixin_); } import std.algorithm; static if(!mixin_.canFind("return")){ return me; } } struct foo{ float f; int uselessfield=1337; bool b; } alias biuldfoo=withMe!(q{f=arg[1];b=arg[0];},foo,bool,float); void main(){ import std.stdio; bool t=true; float fourtwenty=4.20; foo().withMe!q{f=arg[1];b=arg[0];}(t,fourtwenty).writeln; foo().biuldfoo(t,fourtwenty).writeln; }```
Jul 27 2022