Too complicated code for generating a random string?

monarch_dodra monarchdodra at gmail.com
Sat Feb 23 08:41:36 PST 2013


On Saturday, 23 February 2013 at 16:25:45 UTC, Andrei 
Alexandrescu wrote:
> On 2/23/13 4:25 PM, Jens Mueller wrote:
>> auto randomLetter = () =>  letters[uniform (0, 
>> letters.length)];
>> auto randomString = iota(10).map!(_ =>  
>> randomLetter()).array();
>
> auto randomString = iota(10).map!(_ => letters[uniform(0, 
> $)]).array;
>
> Bearophile has long asked for a one-parameter uniform(n) that 
> does what uniform(0, n) does. Perhaps this provides a good 
> supporting argument. With that enhancement:
>
> auto randomString = iota(10).map!(_ => 
> letters[uniform($)]).array;
>
> I expect this to be fast and only allocate once.
>
>
> Andrei

I'm still not a fan of the iota+map combo.

I wrote this (Fast)Generator template. The generic "generator" 
bookkeeps the calls to front and popFront.

The "fast" variant assumes that you'll basically just call 
front+popFront+front+popFront, or that you don't about bookeeping.

This can be interesting, as often, iota+map is straight up 
linearly consumed.

//----
import std.stdio, std.range, std.conv, std.random;

template zeroaryFun(alias fun)
{
     static if (is(typeof(fun) : string))
     {
         auto zeroaryFun()
         {
             mixin("return (" ~ fun ~ ");");
         }
     }
     else
     {
         alias fun zeroaryFun;
     }
}

struct FastGenerator(alias F)
{
     private alias fun = zeroaryFun!F;
     private alias T = typeof(fun());

     enum empty = false;
     @property auto front() {return fun();}
     void popFront() {}
}
struct Generator(alias F)
{
     private alias fun = zeroaryFun!F;
     private alias T = typeof(fun());
     private T cache;
     private bool called = false;

     enum empty = false;

     @property
     auto front()
     {
         if (!called)
         {
             cache = fun();
             called = true;
         }
         return cache;
     }

     void popFront()
     {
         if (!called)
             fun();
         called = false;
     }
}

void main()
{
     dstring letters = "abcd";
     int i = 0;
     writeln(FastGenerator!(() => (i++))().take(9)); //Who needs 
iota?
     writeln(FastGenerator!"'s'"().take(5)); //Who needs repeat?
     writeln(FastGenerator!(() => letters[uniform(0, 
$)])().take(9)); //Simple,clear,concise.
}
//----

In these cases, Generator is something that is both convenient 
and fast.

I realize it's not an incredibly higher order function or 
anything, but I wouldn't mind having something like this in 
Phobos. It would just make every day coding that much more 
convenient and simple.


More information about the Digitalmars-d mailing list