February 27, 2014 Re: Minor std.stdio.File.ByLine rant | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On Thu, 27 Feb 2014 12:32:44 -0500, H. S. Teoh <hsteoh@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*. Actually, this kind of a solution would be better that what I came up with, because the object itself is a range instead of a delegate (satisfies, for instance, isInputRange and isIterable, whereas the delegate does not), and you don't need the static if like I wrote. Any additional usage of the delegate in my original solution creates a copy of the range, but the above would only construct it once.
-Steve
|
February 28, 2014 Re: Minor std.stdio.File.ByLine rant | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | 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@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 |
February 28, 2014 Re: Minor std.stdio.File.ByLine rant | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On Fri, 28 Feb 2014 16:12:26 -0500, H. S. Teoh <hsteoh@quickfur.ath.cx> wrote:
> 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.
Yes, this is true. So, one can specifically define empty() and let the rest go to alias this.
I think such a range would be a good phobos addition.
-Steve
|
Copyright © 1999-2021 by the D Language Foundation