digitalmars.D.learn - binding arbitrary function arguments
- Thomas (38/38) Jun 27 2007 Hello!
- Kirk McDonald (8/13) Jun 27 2007 Yes! Use std.bind:
- Thomas (5/10) Jun 27 2007 Thanks for the suggestion.
- Jason House (3/18) Jun 27 2007 Why not open bind.d and look at the source? dmd/src/phobos/std/bind.d,
- BCS (106/106) Jun 28 2007 Ohh this is a good one!!
- BCS (6/102) Jul 05 2007 I am a compleat idiot!!! I was trying to pass a type tuple to a function...
Hello! I'm trying to familiarize myself a bit with D translating idioms I'm used to from other languages. Binding function arguments I ran into a problem. Is there a "good" way to bind an arbitrary function argument? I implemented "bind1st", "bind2nd", ... which was not too difficult, but failed when trying to implement "bindNth". Well, that is I managed to write only a rather "ugly" version: Given for example int plus(int a1, int a2)... I can do auto plus_four = bind1st(&plus, 4); plus_four(1); // => 5 but I cannot think of a way to achieve auto plus_four = bindNth(&plus, 1, 4); // binding first argument to 4 plus_four(1); All I got so far is: auto plus_four = bind!(1).Nth(&plus, 4); Any suggestions would be very welcome. Thanks in advance, Thomas The code: template bind(int I) { R delegate(U) Nth(R, A, U...)(R delegate(A, U) dg, A arg) { struct binder { R delegate(A, U) dg_m; A arg_m; R call(U u) { return dg_m(u[0..I-1], arg_m, u[I-1..u.length]); } } binder* b = new binder; b.dg_m = dg; b.arg_m = arg; return &b.call; } }
Jun 27 2007
Thomas wrote:Hello! I'm trying to familiarize myself a bit with D translating idioms I'm used to from other languages. Binding function arguments I ran into a problem. Is there a "good" way to bind an arbitrary function argument?Yes! Use std.bind: http://www.digitalmars.com/d/phobos/std_bind.html -- Kirk McDonald http://kirkmcdonald.blogspot.com Pyd: Connecting D and Python http://pyd.dsource.org
Jun 27 2007
Thanks for the suggestion. Actually I was aware of std.bind. But it does not seem to be capable of binding more than 10 arguments. Well, before I get told that I probably shouldn't use more than ten arguments I should maybe mention that I'm principally interested in learning D. That is I'd like to know if and how this general, "unlimited" binding can be done in D. (For all practical purposes I agree that it's likely not relevant - but for understanding and learning the language it may be.) ThomasIs there a "good" way to bind an arbitrary function argument?Yes! Use std.bind: http://www.digitalmars.com/d/phobos/std_bind.html
Jun 27 2007
Thomas wrote:Why not open bind.d and look at the source? dmd/src/phobos/std/bind.d, or something similar to that.Thanks for the suggestion. Actually I was aware of std.bind. But it does not seem to be capable of binding more than 10 arguments. Well, before I get told that I probably shouldn't use more than ten arguments I should maybe mention that I'm principally interested in learning D. That is I'd like to know if and how this general, "unlimited" binding can be done in D. (For all practical purposes I agree that it's likely not relevant - but for understanding and learning the language it may be.) ThomasIs there a "good" way to bind an arbitrary function argument?Yes! Use std.bind: http://www.digitalmars.com/d/phobos/std_bind.html
Jun 27 2007
Ohh this is a good one!! bind.d(32): function bind.fnc (int,char,bool,int[],float) does not match parameter types ((int, char, bool, int[], float)) BTW this almost does arbitrary binding. |template T(t...){alias t T;} | |template Args(A...) |{ | template Become(V...) | { | static assert(A.length == V.length); | template For(alias fn) | { | static if( | is(typeof(fn) arg == function) && | is(typeof(fn) R == return) | ) | { | alias Remove!(A).From!(arg) pArgs; | static const uint vl = V.length; | alias Remove!(A).From!(range!(0,vl)) map; | | R For(pArgs p) | { | arg set; | foreach(uint i, v; A) | { | set[A[i]] = V[i]; | } | | foreach(uint i, v; map) | { | set[map[i]] = p[i]; | } | | return fn(arg); // line 34 | } | } | else | static assert(false); | } | } |} | |template Remove(R...) |{ | template From(A...) | { | static if(A.length != 0) | { | static if(isIn!(A.length-1, R)) | alias Remove!(R).From!(A[0..$-1]) From; | else | alias T!(Remove!(R).From!(A[0..$-1]), A[$-1]) From; | } | else | alias T!() From; | | } |} | |template isIn(A...) |{ | static assert(A.length != 0); | static if(A.length == 1) | const bool isIn = false; | else | { | static if(A[0] == A[$-1]) | const bool isIn = false; | else | const bool isIn = isIn!(A[0], A[1..$-1]); | } |} | |template range(int start, int stop, A...) |{ | static if(start >= stop) | alias T!(A,start) range; | else | alias range!(start+1, stop, A, start) range; |} | | |import std.stdio; | |int fnc(int that, char has, bool lots, int[] of, float args) |{ | writef("%s, %s, %s, %s, %s\n",that,has,lots,of,args); | return 0; |} | |void f(int i, char c, float f) { writef("%s, %s, %s\n", i,c,f); } | |void main() |{ | alias Args! (0,2, 4). | Become!(1,true,1e7). | For!(fnc) fn2; | fn2(); | | alias T!(int, char, float) A; | A a; | a[0] = 0; a[1] = 'c'; a[2] = 1e5; | f(a); |}
Jun 28 2007
Reply to Benjamin,Ohh this is a good one!! bind.d(32): function bind.fnc (int,char,bool,int[],float) does not match parameter types ((int, char, bool, int[], float)) BTW this almost does arbitrary binding.I am a compleat idiot!!! I was trying to pass a type tuple to a function. Obviously that shouldn't work!!! (p.s. the message isn't that helpful, something like "can't pass non value parameters to function" would be nice) This worksimport std.stdio; int fnc(int that, char has, bool lots, int[] of, float args) { writef("%s, %s, %s, %s, %s\n",that,has,lots,of,args); return 0; } void main() { alias Args! (0,2, 4). Become!(1,true,1e7). For!(fnc).Gives fn2; fn2('c', [1,2,3]); } template T(t...){alias t T;} template Args(A...) { template Become(V...) { static assert(A.length == V.length); template For(alias fn) { static if( is(typeof(fn) arg == function) && is(typeof(fn) R == return) ) { alias Remove!(A).From!(arg) pArgs; static const uint vl = V.length; alias range!(0,vl) imap; alias Remove!(A).From!(imap) map; R Gives(pArgs p) { arg set; foreach(uint i, v; A) { set[A[i]] = V[i]; } foreach(uint i, v; map) { set[map[i]] = p[i]; } return fn(set); // line 34 } } else static assert(false); } } } template Remove(R...) { template From(A...) { static if(A.length != 0) { static if(isIn!(A.length-1, R)) { alias Remove!(R).From!(A[0..$-1]) From; } else { alias T!(Remove!(R).From!(A[0..$-1]), A[$-1]) From; } } else { alias T!() From; } } } template isIn(A...) { static assert(A.length != 0); static if(A.length == 1) const bool isIn = false; else { static if(A[0] == A[$-1]) const bool isIn = true; else const bool isIn = isIn!(A[0], A[1..$-1]); } } template range(int start, int stop, A...) { static if(start >= stop) alias T!(A,start) range; else alias range!(start+1, stop, A, start) range; }
Jul 05 2007