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 > <[email protected]> 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
