On Mon, 26 Sep 2011 12:12:30 -0400, Jonathan M Davis <jmdavisp...@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
<jmdavisp...@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.
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.
-Steve