digitalmars.D.learn - streams to ranges adapters
- Diego Martinelli (31/31) Sep 01 2010 Hi all!
- Jonathan M Davis (9/14) Sep 01 2010 A properly written stream type _is_ a range with no adaptors necessary. ...
- Peter Neubauer (64/69) Sep 01 2010 (something like
- Philippe Sigaud (6/13) Sep 01 2010 It's a good idea and a common need: to transform a generator into a rang...
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). Just a bit of C++ to make my point: #include <iostream> #include <algorithm> #include <vector> #include <iterator> using namespace std; // just for convenience int factorial(const int& n) { int result = 1; for (int i = 1; i <= n; ++i) result *= i; return result; } int main() { vector<int> v; copy(istream_iterator<int>(cin), istream_iterator<int>(), back_inserter(v)); transform(v.begin(), v.end(), ostream_iterator<int>(cout, "\n"), factorial); return 0; } How'd you write an equivalent program in idiomatic D? I mean, I'd like an higher level approach to foreach/readf. Am I missing something? Thanks, Diego
Sep 01 2010
On Wednesday 01 September 2010 03:19:41 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).A properly written stream type _is_ a range with no adaptors necessary. However, std.stream predates much of the range stuff in Phobos, so its implementation does not support ranges. The intention is to replace it with a streaming module that _does_ properly support ranges. However, it's on the TODO list and hasn't been done yet. IIRC, there's at least one implementation which has been discussed on the Phobos list which may end up as the replacement for std.stream, but it hasn't happened yet, so Phobos does not yet support using ranges with streams. - Jonathan M Davis
Sep 01 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 andI can't helpmyself. I feel like there's a lack of adapters between streams and ranges(something likeistream_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
Sep 01 2010
On Wed, Sep 1, 2010 at 20:54, Peter Neubauer <peterneubauer2 gmail.com>wrote: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:(snip)Oh, and I didn't test my code at all, apart from those examples. Feel free to use it if you like.It's a good idea and a common need: to transform a generator into a range. It could be adapted to work with callable structs and classes, too, if you need it to hold state. Philippe
Sep 01 2010