Thread overview
Function Template for Dynamic Parameter
Jul 01, 2018
vino.B
Jul 01, 2018
Timoses
Jul 01, 2018
vino.B
Jul 01, 2018
Alex
Jul 01, 2018
vino.B
Jul 01, 2018
Timoses
Jul 05, 2018
vino.B
Jul 06, 2018
Timoses
Jul 01, 2018
Timoses
July 01, 2018
All,

   Request your help, the D document states that "Template functions are useful for avoiding code duplication - instead of writing several copies of a function, each with a different parameter type, a single function template can be sufficient" which mean we can passing any type of parameter using function template, similarly who we we pass in any number of parameter of any type(dynamic parameters) , like in python

Python

def myfunc(*arg)
def myfunc(**kwargs) // multiple key-value
def myfunc(*args, **kwargs): mix

Do we have any thing similar to the above python in D
void (func(T)( T *args) // Example


Examples:
void func(T)(T x)
{
    writeln(x);
}
void main()
{ func("x");  // pass a string }


void func(T)(T n3)
{
    writeln(n); // where n = 3 parameters (1, string, char)
}

void func(T)(T n2)
{
    writeln(n); // where n = 3 parameters (1, string)
}

void func(T)(T n1)
{
    writeln(n); // where n = 3 parameters (1 or string or char)
}

From,
Vino.B


July 01, 2018
On Sunday, 1 July 2018 at 09:46:32 UTC, vino.B wrote:
> All,
>
>    Request your help, the D document states that "Template functions are useful for avoiding code duplication - instead of writing several copies of a function, each with a different parameter type, a single function template can be sufficient" which mean we can passing any type of parameter using function template, similarly who we we pass in any number of parameter of any type(dynamic parameters) , like in python
>
> Python
>
> def myfunc(*arg)
> def myfunc(**kwargs) // multiple key-value
> def myfunc(*args, **kwargs): mix
>
> Do we have any thing similar to the above python in D
> void (func(T)( T *args) // Example
>
>
> Examples:
> void func(T)(T x)
> {
>     writeln(x);
> }
> void main()
> { func("x");  // pass a string }
>
>
> void func(T)(T n3)
> {
>     writeln(n); // where n = 3 parameters (1, string, char)
> }
>
> void func(T)(T n2)
> {
>     writeln(n); // where n = 3 parameters (1, string)
> }
>
> void func(T)(T n1)
> {
>     writeln(n); // where n = 3 parameters (1 or string or char)
> }
>
> From,
> Vino.B

Perhaps https://dlang.org/spec/template.html#variadic-templates

    void func(T ...)(T args)
    {
        static assert(T.length <= 3);

        static assert(is(T[0] == int)); // 1

        pragma(msg, T.stringof);
        foreach (arg; args)
        {
            writeln(arg);
        }
    }

    void main()
    {
        func(3, "s", 1.3);
        //func(1.3); // error, first argument is not an int, see // 1
    }
July 01, 2018
On Sunday, 1 July 2018 at 09:55:34 UTC, Timoses wrote:
> On Sunday, 1 July 2018 at 09:46:32 UTC, vino.B wrote:
>> All,
>>
>>    Request your help, the D document states that "Template functions are useful for avoiding code duplication - instead of writing several copies of a function, each with a different parameter type, a single function template can be sufficient" which mean we can passing any type of parameter using function template, similarly who we we pass in any number of parameter of any type(dynamic parameters) , like in python
>>
>> Python
>>
>> def myfunc(*arg)
>> def myfunc(**kwargs) // multiple key-value
>> def myfunc(*args, **kwargs): mix
>>
>> Do we have any thing similar to the above python in D
>> void (func(T)( T *args) // Example
>>
>>
>> Examples:
>> void func(T)(T x)
>> {
>>     writeln(x);
>> }
>> void main()
>> { func("x");  // pass a string }
>>
>>
>> void func(T)(T n3)
>> {
>>     writeln(n); // where n = 3 parameters (1, string, char)
>> }
>>
>> void func(T)(T n2)
>> {
>>     writeln(n); // where n = 3 parameters (1, string)
>> }
>>
>> void func(T)(T n1)
>> {
>>     writeln(n); // where n = 3 parameters (1 or string or char)
>> }
>>
>> From,
>> Vino.B
>
> Perhaps https://dlang.org/spec/template.html#variadic-templates
>
>     void func(T ...)(T args)
>     {
>         static assert(T.length <= 3);
>
>         static assert(is(T[0] == int)); // 1
>
>         pragma(msg, T.stringof);
>         foreach (arg; args)
>         {
>             writeln(arg);
>         }
>     }
>
>     void main()
>     {
>         func(3, "s", 1.3);
>         //func(1.3); // error, first argument is not an int, see // 1
>     }

Hi Timoses,

  Thank you very much, can you help me on how to rewrite the below using Variadic template

Passing function as a parameter to another function:

void ptFun(T)(T function(string, string, int) coRoutine, Array!string Dirlst, ) {
alias scRType = typeof(coRoutine(string.init, string.init, int.init));

where the "function(string, string, int) coRoutine" should be a variadic function

From,
Vino.B

July 01, 2018
On Sunday, 1 July 2018 at 11:19:50 UTC, vino.B wrote:
>
> Hi Timoses,
>
>   Thank you very much, can you help me on how to rewrite the below using Variadic template
>
> Passing function as a parameter to another function:
>
> void ptFun(T)(T function(string, string, int) coRoutine, Array!string Dirlst, ) {
> alias scRType = typeof(coRoutine(string.init, string.init, int.init));
>
> where the "function(string, string, int) coRoutine" should be a variadic function
>
> From,
> Vino.B

I'm not sure, if get your question right, is this what you are looking for?


´´´
import std.stdio;
import std.traits;

void main()
{
	alias instantiation = ptFun!(size_t, fun!string);
	
	instantiation(4);

	alias instantiation2 = ptFun2!(fun!string);

	instantiation2(4);

}

auto fun(T...)(T input)
{
	return size_t(42);
}

void ptFun(T, alias funToCall)(size_t definedParam)
	if(is(T == ReturnType!(funToCall)))
{
	"ptFun called".writeln;
	assert(42 == funToCall("some string"));
}

void ptFun2(alias funToCall)(size_t definedParam)
	if(__traits(isSame, TemplateOf!(funToCall), fun))
{
	"ptFun2 called".writeln;
	assert(42 == funToCall("some string"));
}
´´´

July 01, 2018
On Sunday, 1 July 2018 at 11:52:19 UTC, Alex wrote:
> On Sunday, 1 July 2018 at 11:19:50 UTC, vino.B wrote:
>>
>> Hi Timoses,
>>
>>   Thank you very much, can you help me on how to rewrite the below using Variadic template
>>
>> Passing function as a parameter to another function:
>>
>> void ptFun(T)(T function(string, string, int) coRoutine, Array!string Dirlst, ) {
>> alias scRType = typeof(coRoutine(string.init, string.init, int.init));
>>
>> where the "function(string, string, int) coRoutine" should be a variadic function
>>
>> From,
>> Vino.B
>
> I'm not sure, if get your question right, is this what you are looking for?
>
>
> ´´´
> import std.stdio;
> import std.traits;
>
> void main()
> {
> 	alias instantiation = ptFun!(size_t, fun!string);
> 	
> 	instantiation(4);
>
> 	alias instantiation2 = ptFun2!(fun!string);
>
> 	instantiation2(4);
>
> }
>
> auto fun(T...)(T input)
> {
> 	return size_t(42);
> }
>
> void ptFun(T, alias funToCall)(size_t definedParam)
> 	if(is(T == ReturnType!(funToCall)))
> {
> 	"ptFun called".writeln;
> 	assert(42 == funToCall("some string"));
> }
>
> void ptFun2(alias funToCall)(size_t definedParam)
> 	if(__traits(isSame, TemplateOf!(funToCall), fun))
> {
> 	"ptFun2 called".writeln;
> 	assert(42 == funToCall("some string"));
> }
> ´´´

Hi Alex,

  Something similar to the below code, when compling the below code i get an error

NewType.d(19): Error: function declaration without return type. (Note that constructors are always named this)

import core.time: days;
import std.algorithm: each, filter, map, sort, strip;
import std.container.array;
import std.conv: to;
import std.datetime.systime: Clock, SysTime;
import std.file: dirEntries, isFile, SpanMode;
import std.parallelism: parallel;
import std.stdio: File, writefln, writeln;
import std.string: strip;
import std.traits: ReturnType;
import std.typecons: Tuple, tuple;

auto coCleanFiles(T ...)(T args) {
	auto dFiles = Array!(Tuple!(string, SysTime))(dirEntries(FFs, SpanMode.shallow).filter!(a => a.isFile).map!(a => tuple(a.name, a.timeLastModified)));
	return dFiles;
}

void ptManagecoRoutine(T)(T function(T ...)(T args), Array!string Dirlst) {
    alias scRType = typeof(coRoutine(args.init));
    auto PFresult = taskPool.workerLocalStorage!scRType;
    ReturnType!coRoutine rData;
    foreach (string FFs; Dirlst[]) { PFresult.get ~= coRoutine(FFs.strip); }
    foreach(i; PFresult.toRange) { rData ~= i[][]; }
    if (!rData[].empty) { rData[].sort!((a,b) => a[1] < b[1]).each!(e => writefln!"%-83s %.20s"(e[0], e[1].to!string)); }
}
 void main () {
 Array!string CleanDirlst;
 CleanDirlst.insertBack("C:\\Temp\\BACKUP1");
 ptManagecoRoutine(&coCleanFiles, CleanDirlst);
 }

From,
Vino.B
July 01, 2018
On Sunday, 1 July 2018 at 11:19:50 UTC, vino.B wrote:
> On Sunday, 1 July 2018 at 09:55:34 UTC, Timoses wrote:>
> Hi Timoses,
>
>   Thank you very much, can you help me on how to rewrite the below using Variadic template
>
> Passing function as a parameter to another function:
>
> void ptFun(T)(T function(string, string, int) coRoutine, Array!string Dirlst, ) {
> alias scRType = typeof(coRoutine(string.init, string.init, int.init));
>
> where the "function(string, string, int) coRoutine" should be a variadic function

What's your use case?

You can pretty much pass anything to a template and use "static if" and "static foreach" in the template to steer how the template is instantiated.

    void func(T ...)(T args)
    {
        foreach (i, arg; args)
        {
            static if (isSomeFunction!(T[i]))
            {
                arg();
            }
            else
                writeln(arg);
        }
    }

    unittest
    {
        func(() => writeln("I'm a lambda function), "I'm a string", 3);
    }

which would print:

I'm a lambda function
I'm a string
3


I'm actually a bit suprised that `isSomeFunction!(T[i])` works here, I'd expect an error because `i` looks like a run-time variable... And using that in a compile-time (static if) statement usually throws a CT error.


With templates one has to think "compile-time". Any "static if", "static foreach" or alias declarations are compile time constructs. What results from that after compilation is an instantiated template for a specific use case. For example in above case the template exists (is instantiated) with the template parameters `(void function() @safe, string, int)`.

A good source to get some more insights is always:
http://ddili.org/ders/d.en/templates.html
(including all other sections of the book)
July 01, 2018
On Sunday, 1 July 2018 at 11:58:30 UTC, vino.B wrote:
> On Sunday, 1 July 2018 at 11:52:19 UTC, Alex wrote:
> NewType.d(19): Error: function declaration without return type. (Note that constructors are always named this)
>
> [...]
>
> auto coCleanFiles(T ...)(T args) {
> 	auto dFiles = Array!(Tuple!(string, SysTime))(dirEntries(FFs, SpanMode.shallow).filter!(a => a.isFile).map!(a => tuple(a.name, a.timeLastModified)));
> 	return dFiles;
> }
>
> void ptManagecoRoutine(T)(T function(T ...)(T args), Array!string Dirlst) {
>     alias scRType = typeof(coRoutine(args.init));
>     auto PFresult = taskPool.workerLocalStorage!scRType;
>     ReturnType!coRoutine rData;
>     foreach (string FFs; Dirlst[]) { PFresult.get ~= coRoutine(FFs.strip); }
>     foreach(i; PFresult.toRange) { rData ~= i[][]; }
>     if (!rData[].empty) { rData[].sort!((a,b) => a[1] < b[1]).each!(e => writefln!"%-83s %.20s"(e[0], e[1].to!string)); }
> }
>  void main () {
>  Array!string CleanDirlst;
>  CleanDirlst.insertBack("C:\\Temp\\BACKUP1");
>  ptManagecoRoutine(&coCleanFiles, CleanDirlst);
>  }


auto coCleanFiles(T ...)(T args)
{ ... }

void ptManagecoRoutine(T)(T fun, Array!string DirList)
{
    foreach (dir; DirList)
        fun(dir);
}

or

 void ptManagecoRoutine2(alias func)(Array!string DirList)
       if (is (typeof(func!(typeof(DirList[0]))) == function))
 {
     alias t = typeof(DirList[0]);
     ptManagecoRoutine(&func!t, DirList);
 }

callable via

Array!string CleanDirlst;
ptManagecoRoutine(&coCleanFiles!string, CleanDirlst);
ptManagecoRoutine2!coCleanFiles(CleanDirlst);

July 05, 2018
On Sunday, 1 July 2018 at 12:46:30 UTC, Timoses wrote:
> On Sunday, 1 July 2018 at 11:58:30 UTC, vino.B wrote:
>> On Sunday, 1 July 2018 at 11:52:19 UTC, Alex wrote:
>> NewType.d(19): Error: function declaration without return type. (Note that constructors are always named this)
>>
>> [...]
>>
>> auto coCleanFiles(T ...)(T args) {
>> 	auto dFiles = Array!(Tuple!(string, SysTime))(dirEntries(FFs, SpanMode.shallow).filter!(a => a.isFile).map!(a => tuple(a.name, a.timeLastModified)));
>> 	return dFiles;
>> }
>>
>> void ptManagecoRoutine(T)(T function(T ...)(T args), Array!string Dirlst) {
>>     alias scRType = typeof(coRoutine(args.init));
>>     auto PFresult = taskPool.workerLocalStorage!scRType;
>>     ReturnType!coRoutine rData;
>>     foreach (string FFs; Dirlst[]) { PFresult.get ~= coRoutine(FFs.strip); }
>>     foreach(i; PFresult.toRange) { rData ~= i[][]; }
>>     if (!rData[].empty) { rData[].sort!((a,b) => a[1] < b[1]).each!(e => writefln!"%-83s %.20s"(e[0], e[1].to!string)); }
>> }
>>  void main () {
>>  Array!string CleanDirlst;
>>  CleanDirlst.insertBack("C:\\Temp\\BACKUP1");
>>  ptManagecoRoutine(&coCleanFiles, CleanDirlst);
>>  }
>
>
> auto coCleanFiles(T ...)(T args)
> { ... }
>
> void ptManagecoRoutine(T)(T fun, Array!string DirList)
> {
>     foreach (dir; DirList)
>         fun(dir);
> }
>
> or
>
>  void ptManagecoRoutine2(alias func)(Array!string DirList)
>        if (is (typeof(func!(typeof(DirList[0]))) == function))
>  {
>      alias t = typeof(DirList[0]);
>      ptManagecoRoutine(&func!t, DirList);
>  }
>
> callable via
>
> Array!string CleanDirlst;
> ptManagecoRoutine(&coCleanFiles!string, CleanDirlst);
> ptManagecoRoutine2!coCleanFiles(CleanDirlst);

Hi All,

  Request your help on the below code

auto coCleanFiles(T ...) (T FFs) {
    auto dFiles = Array!(Tuple!(string, SysTime))(dirEntries(FFs, SpanMode.depth).map!(a => tuple(a.name, a.timeCreated)));
	return dFiles;
}

void process(T)(T pfunction, Array!string Dirlst) {
alias wlsType = typeof(pfunction(T));
auto Result = taskPool.workerLocalStorage!wlsType();
foreach (FFs; parallel(Dirlst[],1)) { Result.get ~= pfunction(FFs); }
foreach(i; Result.toRange) { writeln(i[][]); }
}

void main() {
Array!string Cleanlst;
Cleanlst.insert("C:\\Temp\\BACKUP1");
process(&coCleanFiles, Cleanlst);
}

Error : Error: coCleanFiles(T...)(T FFs) is not an lvalue and cannot be modified

From,
Vino.B
July 06, 2018
On Thursday, 5 July 2018 at 16:23:36 UTC, vino.B wrote:
> Hi All,
>
>   Request your help on the below code
>
> auto coCleanFiles(T ...) (T FFs) {
>     auto dFiles = Array!(Tuple!(string, SysTime))(dirEntries(FFs, SpanMode.depth).map!(a => tuple(a.name, a.timeCreated)));
> 	return dFiles;
> }
>
> void process(T)(T pfunction, Array!string Dirlst) {
> alias wlsType = typeof(pfunction(T));
> auto Result = taskPool.workerLocalStorage!wlsType();
> foreach (FFs; parallel(Dirlst[],1)) { Result.get ~= pfunction(FFs); }
> foreach(i; Result.toRange) { writeln(i[][]); }
> }
>
> void main() {
> Array!string Cleanlst;
> Cleanlst.insert("C:\\Temp\\BACKUP1");
> process(&coCleanFiles, Cleanlst);
> }
>
> Error : Error: coCleanFiles(T...)(T FFs) is not an lvalue and cannot be modified

I guess since in above code `coCleanFiles` is a template, you can not simply take the address of that function template. You'd have to instantiate the template first

    process(&coCleanFiles!string, ...)

If you want to pass the template to process you could define process as something like

    void process(alias func)(Array!string Dirlst)
    {
        func!string(Dirlst[0]);
    }

and call

    process!coCleanFiles(Cleanlst);