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.

Reply via email to