On Tuesday, 25 January 2022 at 09:48:25 UTC, forkit wrote:
so I'm trying to write (or rather learn how to write) a
'variadic template function', that returns just one of its
variadic parameter, randomly chosen.
But can't get my head around the problem here :-(
.. Error: template `std.random.randomSample` cannot deduce
function from argument types `
// --
module test;
import std;
string RandomChoice(R...)(R r)
{
auto rnd = MinstdRand0(42);
return r.randomSample(1, rnd).to!string;
}
void main()
{
writeln( RandomChoice("typeA", "typeB", "typeC") );
}
// --
On Tuesday, 25 January 2022 at 09:48:25 UTC, forkit wrote:
so I'm trying to write (or rather learn how to write) a
'variadic template function', that returns just one of its
variadic parameter, randomly chosen.
But can't get my head around the problem here :-(
.. Error: template `std.random.randomSample` cannot deduce
function from argument types `
// --
module test;
import std;
string RandomChoice(R...)(R r)
{
auto rnd = MinstdRand0(42);
return r.randomSample(1, rnd).to!string;
}
void main()
{
writeln( RandomChoice("typeA", "typeB", "typeC") );
}
// --
With R... each value could be of different type, so passing
`RandomChoice("typeA", 4)` would break the current code.
I think there are 2 different ways that can solve this elegantly:
1) restrict the parameters to all be the same parameter type:
```d
string RandomChoice(T)(T[] r...)
{
auto rnd = MinstdRand0(42);
return r.randomSample(1, rnd).to!string;
}
```
and code compiles with no changes. Instead of using
.to!string you could also return the parameter type itself if you
want to get the value itself:
```d
T RandomChoice(T)(T[] r...)
{
auto rnd = MinstdRand0(42);
return r.randomSample(1, rnd).front;
}
```
2) generate a random number between 0 and `r.length`, add a
switch case and dynamically generate a case for each number
(static foreach) and return the processed value using .to!string:
```d
string RandomChoice(R...)(R r)
{
auto rnd = MinstdRand0(42);
switch (uniform(0, R.length, rnd))
{
static foreach (i, value; r)
{
case i: // this code is duplicated for each
parameter
// use this if you want to support different
argument types
return value.to!string;
}
default: assert(false);
}
}
```