Passing function(whose parameter would be dynamic and the type is unknown) as a parameter to another function.

Simen Kjærås simen.kjaras at gmail.com
Mon Jul 9 07:39:41 UTC 2018


On Monday, 9 July 2018 at 05:54:27 UTC, vino.B wrote:
>
> In phase 2 we are transferring few more function to the 
> existing D code, and these functions has variable number of 
> parameter and different type eg: Function3(string, string, 
> string), Function(string, int, string, int).
>
> Initially I tried to re-write the ptManager function for each 
> type of function which ended with 8 ptManager functions, Eg : 
> ptManager1(string, string, int), ptManager2(string, string, 
> string), ptManager3(string,int), so now trying as to whether we 
> can use 1 ptManager function which can process function with 
> “N” of parameter and types to process all the function, hence 
> trying to implement the Variadic function. Hence request your 
> help and suggestion to achieve this.


Variadic templates to the rescue:

void ptManager1(Fn, Args...)(Fn coRoutine, Array!string Dirlst, 
Args args)
if (__traits(compiles, coRoutine("", args)))
{
     alias scRType = typeof(coRoutine("", args));
     auto PFresult = taskPool.workerLocalStorage!scRType();
     foreach (string FFs; parallel(Dirlst[], 1)) {
         PFresult.get ~= coRoutine(FFs.strip, args);
     }
     foreach(i; PFresult.toRange) { writeln(i[][]); }
}

unittest {
     ptManager1(&function1, Fn1Dirlst, Step, Size);
     ptManager1(&function2, Fn2Dirlst, Step, Age);
}


Alternatively, pass the co-routine as an alias:

void ptManager2(alias coRoutine, Args...)(Array!string Dirlst, 
Args args)
if (__traits(compiles, coRoutine("", args)))
{
     alias scRType = typeof(coRoutine("", args));
     auto PFresult = taskPool.workerLocalStorage!scRType();
     foreach (string FFs; parallel(Dirlst[], 1)) {
         PFresult.get ~= coRoutine(FFs.strip, args);
     }
     foreach(i; PFresult.toRange) { writeln(i[][]); }
}

unittest {
     ptManager2!function1(Fn1Dirlst, Step, Size);
     ptManager2!function2(Fn2Dirlst, Step, Age);
}

These options are essentially equivalent; the main reason to 
prefer the first is if the functions are passed around at 
runtime. If you don't do that, ptManager2 may be slightly faster.

Using logE and logF is left as an exercise for the reader. :p


As an aside, I first thought of making a less generic ptManager 
that'd work something like this:

     ptManager3(dir => function1(dir, Step, Size), Fn1Dirlst);

However, since the return value changes between functions, that 
doesn't really buy us much - we'll still have to templatize 
ptManager3 on the return type, and the contents of the function 
will be very much the same.

--
   Simen


More information about the Digitalmars-d-learn mailing list