digitalmars.D.learn - Templates and unaryFun!
- ddcovery (12/64) Sep 24 2020 Last week, in general forum someone introduced the possibility to
- WebFreak001 (23/30) Sep 24 2020 the problem is the template can't automatically determine the
Last week, in general forum someone introduced the possibility to implement the .? operator in D: https://forum.dlang.org/thread/blnjoaleswqnaojoulzp forum.dlang.org I decided to implement a simple solution with a funciontal syntax:string fatherName = dot(person).dot(a=>a.father).dot(a=>a.name).get("unknown"); Person grandFather = dot(person).dot(a=>a.father).dot(a=>a.father).get;That are equivalent to (dart code)String fatherName = person?.father?.name??"unknown" Person grandFather = person?.father?.fatherThe code isauto dot(T)(T t){ return Dot!T(t); } struct Dot(T) { private Nullable!T value; // = Nullable!T.init; this (T v) { static if(isAssignable!(T, typeof(null) )) { if(v !is null){ value = nullable(v); } } else { value = nullable(v); } } template dot(R) { Dot!R dot( R function(T) fun) { static assert(!isAssignable!(typeof(null), R), "Sorry, f returning type can't be typeof(null)"); return value.isNull() ? Dot!R() : Dot!R(fun(value.get())); } } } T get(T defaultValue) { return this.value.get(defaultValue); } static if(isAssignable!(T, typeof(null) )) { T get() { return this.value.isNull ? null : this.value.get; } } }I tried to adapt to template syntax (as a syntax sugar):auto name = dot(person).dt!"a.father".dt!"a.father".get;but I have not succeeded Example: I tried with a global functionDot!R dt(alias fun, T, R)(Dot!T t){ auto f = cast(R function(T)) unaryFun!fun; return t.dot!R(f); }I really need to investigate more about unaryFun! :-) I will appreciate any idea/guidance Thank you!!!
Sep 24 2020
On Thursday, 24 September 2020 at 11:15:11 UTC, ddcovery wrote:[...] Example: I tried with a global functionthe problem is the template can't automatically determine the type "R". All the template parameters need to be resolvable from the arguments you pass into it, R is something magic where it doesn't know where it comes from. To keep the R like you want to right now you can do the following: Dot!(typeof(unaryFun!fun(T.init))) dt(alias fun, T)(Dot!T t){ return t.dot(t => unaryFun!fun(t)); } or Dot!R dt(alias fun, T, R = typeof(unaryFun!fun(T.init)))(Dot!T t){ return t.dot(t => unaryFun!fun(t)); } Note that this might instantiate unaryFun twice though. The second alternative here allows users to overwrite R and just provides a default (might have useful use cases too) Alternatively a lot easier would be to just return auto and do: auto dt(alias fun, T)(Dot!T t){ return t.dot(t => unaryFun!fun(t)); } This doesn't allow users to overwrite the return type exactly but it simplifies implementation and doesn't look like it would generate any double instantiation.Dot!R dt(alias fun, T, R)(Dot!T t){ auto f = cast(R function(T)) unaryFun!fun; return t.dot!R(f); }[...]
Sep 24 2020
I think I will dedicate tonight one or two hours to understand the first two proposals :-D. On Thursday, 24 September 2020 at 13:28:25 UTC, WebFreak001 wrote:[...] Alternatively a lot easier would be to just return auto and do: auto dt(alias fun, T)(Dot!T t){ return t.dot(t => unaryFun!fun(t)); } This doesn't allow users to overwrite the return type exactly but it simplifies implementation and doesn't look like it would generate any double instantiation. [...]Following your last recommendation, I included de auto version as a Dot(T) member:auto d(alias fun)() { return dot(a => unaryFun!fun(a)); }And the syntax is really compact:assert( dot(p).d!"a.father".d!"a.father".d!"a.name".d!"a.length".get(0) == 0); assert( dot!Person(null).d!"a.father".d!"a.father".d!"a.father".d!"a.name".get == null);Great help WebFreak001. Thank you very much !!!
Sep 24 2020
On Thursday, 24 September 2020 at 14:15:01 UTC, ddcovery wrote:[...] I think I will dedicate tonight one or two hours to understand the first two proposals :-D. [...]Not necessary, really simple and well explained WebFreak001!!!
Sep 24 2020