Possible way to achieve lazy loading with const objects
Steven Schveighoffer
schveiguy at yahoo.com
Mon Sep 26 12:02:24 PDT 2011
On Mon, 26 Sep 2011 13:57:04 -0400, Jonathan M Davis <jmdavisProg at gmx.com>
wrote:
> 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:
>> >
>> > 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_.
That is not a good reason :) Of course, any lazy initializers would have
to be called during compilation time if the variable is put into ROM! Any
lazy initializer that doesn't run during CTFE would result in a compiler
error.
>> 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.
Forgive me for objecting, but a lazy-initialization scheme that eagerly
initializes isn't even a valid solution. I don't mean to be blunt, but I
just can't put it any other way.
I see that you intended it to work lazily for non-const non-immutable
items, but what would be the point then? I can implement lazy
initialization on mutable types today.
> 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.
I think a better avenue would be to implement some sort of strong-pure
memoization system. Then all you have to do is make an immutable pure
member, and the compiler will take care of the rest for you.
I think this only works for classes, however, since there is no place to
put hidden memoization members.
-Steve
More information about the Digitalmars-d
mailing list