passing a variadic parameter to randomSample

WebFreak001 d.forum at webfreak.org
Tue Jan 25 12:29:40 UTC 2022


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


More information about the Digitalmars-d-learn mailing list