Thread overview | ||||||||
---|---|---|---|---|---|---|---|---|
|
April 02, 2014 How to repeat a function call? | ||||
---|---|---|---|---|
| ||||
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 |
April 02, 2014 Re: How to repeat a function call? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen Kjærås | 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. |
April 02, 2014 Re: How to repeat a function call? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen Kjærås | On Wednesday, 2 April 2014 at 19:02:29 UTC, Simen Kjærås wrote:
> Better ideas, please?
>
> --
> Simen
I 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.
|
April 02, 2014 Re: How to repeat a function call? | ||||
---|---|---|---|---|
| ||||
Posted in reply to w0rp | 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))); } |
April 02, 2014 Re: How to repeat a function call? | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | 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:
>> Better ideas, please?
>>
>> --
>> Simen
>
> I 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.
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*.
|
April 02, 2014 Re: How to repeat a function call? | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | On 2014-04-02 20:48, monarch_dodra wrote:
> 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:
>>> Better ideas, please?
>>>
>>> --
>>> Simen
>>
>> I 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.
>
> 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*.
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!
--
Simen
|
Copyright © 1999-2021 by the D Language Foundation