Minor std.stdio.File.ByLine rant

H. S. Teoh hsteoh at quickfur.ath.cx
Fri Feb 28 13:12:26 PST 2014


On Thu, Feb 27, 2014 at 01:47:49PM -0500, Steven Schveighoffer wrote:
> On Thu, 27 Feb 2014 12:32:44 -0500, H. S. Teoh
> <hsteoh at quickfur.ath.cx> wrote:
> 
> >Actually, now that I think about it, can't we just make ByLine lazily
> >constructed? It's already a wrapper around ByLineImpl anyway (since
> >it's being refcounted), so why not just make the wrapper create
> >ByLineImpl only when you actually attempt to use it? That would solve
> >the problem: you can call ByLine but it won't block until ByLineImpl
> >is actually created, which is the first time you call ByLine.empty.
> 
> I think this isn't any different than making ByLine.empty cache the
> first line.
> 
> My solution is basically this:
> 
> struct LazyConstructedRange(R)
> {
>   R r;
>   bool isConstructed = false;
>   R delegate() _ctor;
> 
>   this(R delegate() ctor) {_ctor = ctor;}
> 
>   ref R get() {
>     if(!isConstructed) { r = _ctor(); isConstructed = true;}
>     return r;
>   }
> 
>   alias get this;
> }
> 
> Basically, we're not constructing on first call to empty, but first
> call to *anything*.
[...]

According to a strict interpretation of the range API, it is invalid to
call any range method before you call .empty, because if the range turns
out to be empty, calling .front or .popFront is undefined. So it is
sufficient to implement lazy construction for .empty alone. All other
cases *should* break anyway. :)

Once you have that, then what you're proposing is no different from
mine, in essence.


T

-- 
By understanding a machine-oriented language, the programmer will tend
to use a much more efficient method; it is much closer to reality. -- D.
Knuth


More information about the Digitalmars-d mailing list