digitalmars.D.learn - How to repeat a function call?
- =?ISO-8859-1?Q?Simen_Kj=E6r=E5s?= (40/40) Apr 02 2014 I'm trying to create a function that repeats a function call N times.
- w0rp (27/27) Apr 02 2014 tuples are definitely a compile-time job. You could do something
- monarch_dodra (5/16) Apr 02 2014 auto initTuple(size_t N, alias func)()
- monarch_dodra (7/10) Apr 02 2014 I only skimmed through your post, but have you tried taking a
- monarch_dodra (5/16) Apr 02 2014 Indeed, "assert(adjoin!(Repeat!(3, ()=>a++))() == tuple(0,1,2));"
- =?UTF-8?B?U2ltZW4gS2rDpnLDpXM=?= (7/24) Apr 02 2014 True, in the case of a++, it's probably a bad idea. In my case, the
I'm trying to create a function that repeats a function call N times. The exact use case is generating an N-dimensional tuple: import std.typetuple; import std.typecons; template Repeat(size_t n, T...) { static if (n == 1) { alias Repeat = T; } else static if (n) { alias Repeat = TypeTuple!(Repeat!(n /2, T), Repeat!((n +1)/2, T)); } else { alias Repeat = TypeTuple!(); } } auto fun1(size_t dim, T)(lazy T fn) { return tuple(Repeat!(dim, fn)); } auto fun2(size_t dim, alias fn)() { return tuple(Repeat!(dim, fn)); } void main() { int a = 0; assert(fun1!3(a++) == tuple(0,1,2)); // assert(fun2!(3, ()=>a++) == tuple(0,1,2)); } Now, the call to fun1 works great. But I'd like to specify fn at compile-time, thus doing something more like fun2. fun2 of course, does not work (else why would I ask?). I tried staticMap'ing a template that calls its parameter over the result of Repeat in Fun2, but that did not work: template call(alias fn) { alias call = TypeTuple!(fn()); } auto fun3(size_t dim, alias fn)() { return tuple(staticMap!(call, Repeat!(dim, fn))); } fun3 ends up trying to evaluate the function call at compile-time, and fails because a++ can't be executed until run-time. Better ideas, please? -- Simen
Apr 02 2014
tuples are definitely a compile-time job. You could do something like this to build an N tuple by calling a function N many times. --- import std.typecons; int foo() { return 3; } auto initTuple(size_t N, alias func)() { string magic() { string result = "return tuple("; foreach(i; 0..N) { result ~= "func(),"; } result ~= ");"; return result; } mixin(magic()); } void main(string[] argv) { enum Tuple!(int, int, int) tup = initTuple!(3, foo); } --- This just builds the tuple by building up a mixin string which calls the function so many times, with no guarantees about the order of arguments. If you have side-effects in your function though, you probably want to move it runtime anyway and use a range with the 'repeat' function, etc.
Apr 02 2014
On Wednesday, 2 April 2014 at 19:33:28 UTC, w0rp wrote:auto initTuple(size_t N, alias func)() { string magic() { string result = "return tuple("; foreach(i; 0..N) { result ~= "func(),"; } result ~= ");"; return result; } mixin(magic()); }auto initTuple(size_t N, alias func)() { return mixin(q{tuple(%-(%s, %))}.format("func".repeat(N))); }
Apr 02 2014
On Wednesday, 2 April 2014 at 19:02:29 UTC, Simen Kjærås wrote:Better ideas, please? -- SimenI only skimmed through your post, but have you tried taking a look at adjoin? Preferably, the version in head? Something like "adjoin!(repeat!(fun, N))" seems to natively do what you are asking for? I'll re-read your post later tonight, and if I'm misunderstood, I'll try to provide a better solution.
Apr 02 2014
On Wednesday, 2 April 2014 at 19:54:38 UTC, monarch_dodra wrote:On Wednesday, 2 April 2014 at 19:02:29 UTC, Simen Kjærås wrote:Indeed, "assert(adjoin!(Repeat!(3, ()=>a++))() == tuple(0,1,2));" seems to work for me. That said, while I think the behavior is *defined*, I'm not sure it's *specified*.Better ideas, please? -- SimenI only skimmed through your post, but have you tried taking a look at adjoin? Preferably, the version in head? Something like "adjoin!(repeat!(fun, N))" seems to natively do what you are asking for? I'll re-read your post later tonight, and if I'm misunderstood, I'll try to provide a better solution.
Apr 02 2014
On 2014-04-02 20:48, monarch_dodra wrote:On Wednesday, 2 April 2014 at 19:54:38 UTC, monarch_dodra wrote:True, in the case of a++, it's probably a bad idea. In my case, the function is uniform(0.0, 1.0, rng), and I'm happy with it simply being random. Thanks a lot! -- SimenOn Wednesday, 2 April 2014 at 19:02:29 UTC, Simen Kjærås wrote:Indeed, "assert(adjoin!(Repeat!(3, ()=>a++))() == tuple(0,1,2));" seems to work for me. That said, while I think the behavior is *defined*, I'm not sure it's *specified*.Better ideas, please? -- SimenI only skimmed through your post, but have you tried taking a look at adjoin? Preferably, the version in head? Something like "adjoin!(repeat!(fun, N))" seems to natively do what you are asking for? I'll re-read your post later tonight, and if I'm misunderstood, I'll try to provide a better solution.
Apr 02 2014