| 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
Permalink
Reply