On Mon, 26 Sep 2011 13:57:04 -0400, Jonathan M Davis <jmdavisp...@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 <jmdavisp...@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

Reply via email to