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);
        }
    }
    ```

Reply via email to