Possible way to achieve lazy loading with const objects

Jonathan M Davis jmdavisProg at gmx.com
Mon Sep 26 10:57:04 PDT 2011


On Monday, September 26, 2011 10:26 Steven Schveighoffer wrote:
> On Mon, 26 Sep 2011 12:12:30 -0400, Jonathan M Davis <jmdavisProg at gmx.com>
> 
> wrote:
> > On Monday, September 26, 2011 08:01:29 Steven Schveighoffer wrote:
> >> On Sat, 24 Sep 2011 00:11:52 -0400, Jonathan M Davis
> >> <jmdavisProg at gmx.com>
> >> 
> >> wrote:
> >> > Okay. I'm not saying that we should necessarily implement this. I'm
> >> 
> >> just
> >> 
> >> > looking to air out an idea here and see if there are any technical
> >> > reasons why
> >> > it can't be done or is unreasonable.
> >> > 
> >> > Some programmers have expressed annoyance and/or disappointment that
> >> > there is
> >> > no logical const of any kind in D. They generally seem to be trying to
> >> > do one
> >> > of two things - caching return values in member functions or lazily
> >> > loading
> >> > the values of member variables.
> >> 
> >> The major reason for having logical const is to a) store state on the
> >> object that is not considered part of the object, or b) store references
> >> to objects that are not part of the object state.
> >> 
> >> For example, storing a reference to a mutex in an object, or a reference
> >> to an owner object. It's the difference between a "has a" relationship
> >> and a "points to" relationship.
> >> 
> >> Your lazy loading idea does not help at all for these.
> > 
> > I believe that the two main complaints about the lack of logical const
> > which
> > have been coming up in the newsgroup have been the inability to cache the
> > return values of member functions and the inability to lazily load the
> > values
> > of member variables. This is simply an attempt to solve the lazy loading
> > portion of that problem.
> 
> Of course. My point was that your two use cases I think are far less used
> than the refer-to-other-object-but-don't-own-it cases.
> 
> Maybe I'm wrong, it's been a long time since I used C++, and mutable in
> general. But I remember using it when I wanted to have a reference to
> something that was not part of the object.
> 
> >> > 6. If the S being constructed is shared or immutable and __varProp is
> >> > not
> >> > called in the constructor, then __varProp is called immediately after
> >> > the
> >> > constructor (or at the end of the constructor if that works better for
> >> > the
> >> > compiler).
> >> 
> >> Why? What if the calculation is very expensive, and you never access
> >> var?
> >> 
> >> Besides, we can already pro-actively initialize data in an immutable
> >> constructor, what is the benefit here?
> > 
> > The point is that if aren't using immutable or shared, then you can
> > afford to
> > lazy load it, so you can wait to initialize the variable until it's
> > used, but
> > you _can't_ afford to do that in the case of immutable, because the data
> > must
> > be immutable and can't be changed later to do the lazy loading, and you
> > can't
> > afford to do that in the case of shared, because then you have
> > thread-safety
> > issues, so you have to pay the cost upfront in those cases.
> 
> It is only important that the value is constant *when it's read*, not at
> the beginning of the object existence. If you hook the only way to read
> it with a lazy initializer, then the two cases are indistinguishable, or
> using lazy initialization doesn't make sense.
> 
> Let's think of the case where *two* threads are lazily initializing an
> immutable struct. None of the members can be any different, because they
> are immutable, so if the value depends solely on the internal struct data,
> then both initializers will set the *Same value*. Two competing threads
> writing the same value do not result in corruption.

The problem with immutable is that it could (at least in theory) go in read-
only memory, so lazy initalization doesn't work for it _at all_.

> If the initializer depends on some *external state*, if that external
> state is also immutable, same result.
> 
> If the initializer depends on some external state that is *not* immutable,
> then why mark it lazy initialization? What is the point of initializing
> data that depends on something that's changing over time? I can't see the
> point of doing that. This is of course, only if you can't restart the
> initialization (i.e. clear the 'set' flag).
> 
> Note that if you want your proposed behavior you can achieve it by
> defining a constructor that eagerly initializes the variable by simply
> reading it.
> 
> I still don't think this proposal (even one that always lazily
> initializes) gives enough benefit to be included. Why would you want a
> constant lazily-initialized value in a non-immutable struct? If this were
> to mean anything, there would have to be a way to clear the 'set' flag in
> a mutable struct.

People have been complaining about the lack of logical const. The two use 
cases that they seem to have been looking for are the ability cache the 
results of member functions and to lazily load member variables. They want to 
be able to do those things with const and can't (in the case of Peter 
Alexander, he seems to have come to the conclusion that it's bad enough that 
he doesn't use const for anything not related to threaings, though I do find 
that stance a bit odd, since it's _immutable_ that's needed for threading, not 
const). I was merely trying to present a solution to lazy loading that worked 
with const. It would therefore partially solve the issues that people have 
been complaining about.

Personally, I don't think that the feature merits the extra complexity that it 
incurs. I was just proposing a possible solution. And it seems that some folks 
(Peter in particular) don't think that it goes far enough to be of any real 
value anyway (he wants full-on caching, not lazy loading). Personally, I don't 
even remember the last time that I used lazy loading or caching in a type, so 
the feature was never intended for me anyway, and finding out why folks would 
find it useful would really require their input. But there _are_ people who 
have wanted lazy loading to work with const objects; they just also want 
generally caching to work as well, which isn't at all feasible as far as I can 
tell, whereas lazy loading seems like it could be.

- Jonathan M Davis


More information about the Digitalmars-d mailing list