Range of n lines from stdin
Jakob Ovrum
jakobovrum at gmail.com
Fri Dec 27 10:32:27 PST 2013
On Friday, 27 December 2013 at 14:27:01 UTC, Ivan Kazmenko wrote:
> Quick question.
>
> (1) I can do
> n.iota.map!(_ => readln)
> to get the next n lines from stdin.
This has several issues:
* The result claims to have all kinds of range capabilities that
don't make sense at all. Attempting to actually use these
capabilities, likely indirectly through range algorithms, can
cause all kinds of havoc.
* It will allocate a new buffer for the read line every time
`front` is called, which is less granular than `byLine`'s
allocation behaviour.
* If `stdin` (or whatever file) only has `i` number of lines
left in it where `i < n`, the range will erroneously report `n -
i` number of empty lines at the end.
* It's not showing intent as clear as it should be.
> (3) In the particular case of readln, we can substitute it with
> stdin.byLine.take(n)
> but the question remains for other impure functions.
`byLine` with `take` has very different characteristics from
`map` + `readln`, as explained above.
> So, what I ask for is some non-caching repeat for functions
> with side effects. More idiomatic than (1). Is there
> something like that in Phobos?
It's hard generalize. For one, what is the empty condition?
> Is it an OK style to have an impure function in an UFCS chain?
I assume by UFCS chain you mean range compositions in particular.
It's not really about purity; impure links in the chain are fine
(e.g. `byLine`). The issue is when the side effects are the only
result - I think that is very bad style, and should either be
rewritten in terms of return values, or rewritten to use an
imperative style.
Some people think otherwise, and it results in a lot of Phobos
requests for a function that just eagerly evaluates a range and
nothing more (sometimes called `eat`). I have yet to convince
these people that they are wrong :)
> If repeat could know whether its first argument is pure, it
> could then enable or disable front caching depending on
> purity... no way currently?
`readln.repeat(n)` can also be written `repeat(readln(), n)`.
Maybe that makes it more obvious what it does - reads one line
from standard input and passes that to `repeat`, which returns a
range that returns that same line `n` times.
More information about the Digitalmars-d-learn
mailing list