streams to ranges adapters
Peter Neubauer
peterneubauer2 at gmail.com
Wed Sep 1 11:54:22 PDT 2010
On 09/01/2010 12:19 PM, Diego Martinelli wrote:
> Hi all!
> I'm digging the documentation of phobos but I am still learning D and
I can't help
> myself.
> I feel like there's a lack of adapters between streams and ranges
(something like
> istream_iterator/ostream_iterator in STL).
I've encountered a similar problem yesterday. It left me digging through
the Phobos docs for an hour looking for an existing solution :-) Let's
say I have a function (or any D expression,) and I want to turn
consecutive calls to this function into range form. As an example, let's
generate 10 random numbers between 30 and 50. My first attempt was
something like this:
import std.range;
import std.random;
void main ()
{
writeln(take(recurrence!("uniform(30, 50)")(), 10));
}
However, this doesn't work because recurrence refuses to take 0
arguments. Your post prompted me to steal some boilerplate code from the
Phobos source and write this:
struct Rangeof(T)
{
T delegate() _dg;
T _buffer;
bool _called = false;
this(T delegate() dg) { _dg = dg; }
@property bool empty() { return false; }
void popFront()
{
if (!_called) {
_buffer = _dg();
}
_called = false;
}
@property ref T front()
{
if (!_called) {
_buffer = _dg();
_called = true;
}
return _buffer;
}
}
auto rangeof(F)(F func) if (isCallable!F)
{
return Rangeof!(ReturnType!(F))(func);
}
Rangeof!(T) rangeof(T)(lazy T exp) if (!isCallable!T)
{
T callexp (){ return exp; }
return rangeof(&callexp);
}
Now you can turn any expression or function into a proper input range,
compatible with std.range stuff. Example:
writeln(take(rangeof(uniform(30, 50)), 10));
At the risk of overshooting my goal, here's an additional overload for
std.range.take which can now also "take" from a function:
auto my_take(F)(F input, size_t n) if (!isInputRange!F && isCallable!F)
{
return Take!(Rangeof!(ReturnType!(F)))(rangeof(input), n);
}
Which means one less step in usage:
writeln(my_take({ return uniform(30, 50); }, 10));
Oh, and I didn't test my code at all, apart from those examples. Feel
free to use it if you like.
-Peter
More information about the Digitalmars-d-learn
mailing list