Thread overview
Templates and unaryFun!
Sep 24
ddcovery
Sep 24
ddcovery
Sep 24
ddcovery
September 24
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!!!






September 24
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.
September 24
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 !!!

September 24
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!!!