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

vino.B bheeman.vino at hotmail.com
Mon Jul 9 05:54:27 UTC 2018


On Sunday, 8 July 2018 at 19:22:32 UTC, Timoses wrote:
> On Sunday, 8 July 2018 at 18:46:31 UTC, vino.B wrote:
>> Hi All,
>>
>>  Request you help, in the below code we pass the function 
>> "Testfun" as a parameter to another function "process" in 
>> order for the function "process" to work we have to specify 
>> the type of the parameter that is passed to the function "(T 
>> function(string, int) coRoutine, string Test, int Size) ", so 
>> now how do we pass a function whose parameter would be dynamic 
>> and the type is unknown.
>>
>> void process(T)(T function(string, int) coRoutine, string 
>> Test, int Size) {
>
> This would templetize the return type of the coRoutine, thus 
> within that function you could do
>
>     T returnedValue = coRoutine(string.init, int.init);
>
>> alias scRType = typeof(coRoutine(string.init, int.init));
>>
>> Eg:
>>
>> Run1 : process(&Testfun, Test, Size);
>> void process(T ...)(T function(string, int) coRoutine, string 
>> Test) {
>> alias scRType = typeof(coRoutine(string.init, int.init));
>>
>>
>> Run2 : process(&Testfun, Test, Size, Str1);
>> void process(T)(T function(string, int, string) coRoutine, 
>> string Test, int Size, string Str1) {
>> alias scRType = typeof(coRoutine(string.init, int.init, 
>> string.int));
>>
>>
>> Run3 : process(&Testfun, Test);
>> void process(T)(T function(string, string) coRoutine, string 
>> Test, int Size) {
>> alias scRType = typeof(coRoutine(string.init));
>> PFresult.get = coRoutine(args);
>>
>> Some what like this
>>
>> auto Testfun (string FFs, int Size) { return tuple(FFs, Size); 
>> }
>>
>> void process(T ...)(T function(T args) coRoutine, T args) {
>
> This would mean that if you pass a function that returns for 
> example an int, it must also
> - take an int as argument
> - and process has to accept another int
> e.g.
>     process((int i) => i+1, 3);
>
> if T would be (int, string) you would have to pass something 
> like
>
>     process((int i, string s) {
>         return AliasSeq!(int, string); }, // error: not even 
> sure how to express this
>             3, "hello");
>
> where I'm not sure how to express the return type of (int, 
> string)... Does anybody know this? Would the Tuple Dip make 
> this possible? 
> (https://forum.dlang.org/post/p3bdp1$2b4e$1@digitalmars.com)
>
>> alias scRType = typeof(coRoutine(T.init));
>> PFresult.get = coRoutine(T);
>>
>> void main() {
>> string Test ="C:\\Temp\\BACKUP1"; int Size = 1;
>> process(&Testfun, Test, Size);
>> }
>>
>>
>> Code : Working
>> import std.stdio: writeln;
>> import std.container.array;
>> import std.typecons: tuple;
>> import std.parallelism: taskPool;
>>
>> auto Testfun (string FFs, int Size) { return tuple(FFs, Size); 
>> }
>>
>> void process(T)(T function(string, int) coRoutine, string 
>> Test, int Size) {
>> alias scRType = typeof(coRoutine(string.init, int.init));
>> auto PFresult = taskPool.workerLocalStorage!scRType();
>> PFresult.get = coRoutine(Test, Size);
>> foreach(i; PFresult.toRange) { writeln(i[][]); }
>> }
>>
>> void main() {
>> string Test ="C:\\Temp\\BACKUP1"; int Size = 1;
>> process(&Testfun, Test, Size);
>> }
>>
>> From,
>> Vino.B
>
> I suggest taking a look at 
> https://dlang.org/phobos/std_traits.html .
>
> E.g. ReturnType and Parameters:
>
>     int func() { return 3; }
>     assert(is(ReturnType!func == int));
>
>     void gunc(int i, double j) {}
>     import std.meta : AliasSeq;
>     assert(is(Parameters!gunc == AliasSeq!(int, double)));
>
>
> Perhaps you could tell us what your goal is. People here might 
> come up with a nice solution. Why do you feel like having to 
> use templated functions in the first place? That is, what is 
> the generic goal of the functions you are trying to define?

Hi Timoses,

  We are converting a Power shell script to D in phased manner; 
the PS script has many functions and we converted few function to 
D in Phase 1.

Phase 1:

Structure of the Program
   Main -> Thread Manager->CoFunction1(Fs1,2,3,4,5)
   Main -> Thread Manager->CoFunction2(Fs1,2,3,4,5)


The thread manager will call the Cofunctions and the function 
gets executed on “N” of file systems each of size 5-10 TB.

The function that we transformed all has the same number of 
parameters (3) and the type was same (string, string, int), so we 
wrote a static thread manager as below

void ptManager (T)(T function(string, string, int) coRoutine, 
Array!string Dirlst, string Step, int Size) {
      alias scRType = typeof(coRoutine(string.init, string.init, 
int.init));
      auto PFresult = taskPool.workerLocalStorage!scRType();
      ReturnType!coRoutine rData;
     foreach (string FFs; parallel(Dirlst[0 .. $],1)) { 
PFresult.get ~= coRoutine(FFs.strip, Step); }
      foreach(i; PFresult.toRange) { writeln(i[][]); }
}

void main () {
ptManager(&function1, Fn1Dirlst, Step, Size);
ptManager(&function2, Fn2Dirlst, Step, Age);

}

Phase 2:

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.

Command Parameter to all the functions:
Array!string Dirlist : This parameter will contain the the Fs 
names
File logF: This parameter is used to store the outoput
File logE: This parameter is used to store the Error Information.

Rest of the function has variable parameters/type.

From,
Vino.B






More information about the Digitalmars-d-learn mailing list