Arguably, the goal is to actually replace "repeat+map". I view the fact that iota not being infinite as a drawback. And even if you do want a bound to the length of your range, I believe it should be the "top" step in your types, as opposed to the "bottom" step. Eg:

iota(n).map!(_ => letters[uniform(0, $)]).array;
vs
repeat(0).map!(_ => letters[uniform(0, $)]).take(n).array;

*Personally*, I prefer the logic behind the repeat+map+take, over iota+map's. It might actually even be faster. It is slightly more verbose though :/

There is a way to have an infinite generate range and also a convenient way to initialize arrays - just add an overload of array() that takes the length as the second parameter. Then we can do:

auto randomString = generate!(() => letters[uniform(0, $)]).array(10);

------
Another advantage "generate" would have over repeat+map is if you want to pass an actual named impure function (as opposed to lambda):

iota(0, n).map(_ => fun());
or
repeat(0).map(_ => fun()).take(n);
vs
fastGenerate!fun().take(n);

Here, the generate would be much more "idiomatic", and also probably easier on the compile (function vs lamba: easier inlining, as you mention below).

In general, named functions and lambdas are pretty much equivalent in regard to inlining (see http://goo.gl/XaOUP). In your example, the last line could be more efficient than the first two, because in the first two lines there could be one extra function call in the worst case.

Another thing I'd like to re-bring up (which I've partially implemented already), was bearophile's pass/tee suggestion:
http://forum.dlang.org/thread/[email protected]

I agree this is a good idea.

Reply via email to