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