www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Templates and unaryFun!

reply ddcovery <antoniocabreraperez gmail.com> writes:
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?.father
The code is
 auto 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 function
 Dot!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
parent reply WebFreak001 <d.forum webfreak.org> writes:
On Thursday, 24 September 2020 at 11:15:11 UTC, ddcovery wrote:
 [...]
 Example: I tried with a global function

 Dot!R dt(alias fun, T, R)(Dot!T t){
  auto f = cast(R function(T)) unaryFun!fun;
  return t.dot!R(f);
 }
[...]
the 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.
Sep 24 2020
parent reply ddcovery <antoniocabreraperez gmail.com> writes:
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
parent ddcovery <antoniocabreraperez gmail.com> writes:
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