www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Function Template for Dynamic Parameter

reply vino.B <bheeman.vino hotmail.com> writes:
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
Jul 01 2018
parent reply Timoses <timosesu gmail.com> writes:
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 }
Jul 01 2018
parent reply vino.B <bheeman.vino hotmail.com> writes:
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
Jul 01 2018
next sibling parent reply Alex <sascha.orlov gmail.com> writes:
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")); } ´´´
Jul 01 2018
parent reply vino.B <bheeman.vino hotmail.com> writes:
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
Jul 01 2018
parent reply Timoses <timosesu gmail.com> writes:
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);
Jul 01 2018
parent reply vino.B <bheeman.vino hotmail.com> writes:
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
Jul 05 2018
parent Timoses <timosesu gmail.com> writes:
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);
Jul 06 2018
prev sibling parent Timoses <timosesu gmail.com> writes:
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)
Jul 01 2018