Lazily Initialized Variables that are Compatible with const/immutable

Timon Gehr timon.gehr at gmx.ch
Fri Nov 18 10:59:54 UTC 2022


On 18.11.22 10:00, Vijay Nayar wrote:
> On Thursday, 17 November 2022 at 22:01:21 UTC, Timon Gehr wrote:
>> On 17.11.22 22:49, Vijay Nayar wrote:
>>> On Thursday, 17 November 2022 at 15:33:47 UTC, razyk wrote:
>>>> On 17.11.22 13:04, MorteFeuille123 wrote:
>>>>>>
>>>
>>> While the solutions from razyk and Ali take care of lazy 
>>> initialization, with Ali's solution also having the benefit of being 
>>> thread-safe, none of these methods are actually compatible with 
>>> `const` or `immutable`, meaning that in any case where lazy 
>>> initialization is needed, you cannot have a const class, you have to 
>>> pick one or the other in the current setup.
>>
>> Well, that's what `const` and `immutable` mean. If you need to 
>> restrict mutation in some other way, classic encapsulation works.
>>
>> Note that it is not all that often appropriate to use those qualifiers 
>> when writing traditional OO code.
> 
> In response to this argument, I would cite the Dart language's 
> implementation of `late` variables: 
> https://dart.dev/guides/language/language-tour#late-variables
> 
> To its core, Dart is fully object oriented, and it makes frequent use of 
> immutable and const values

I am not sure what the point is. Dart does not support D const/immutable 
and D does not support Dart final/const. They are different.

D's built-in qualifiers really don't mix well with OO. One reason is the 
embarrassing limitation that there is no way to tail-qualify a class 
reference. Another reason is that "absolutely no mutation" is often 
incompatible with encapsulation as you may want to cache results or 
lazily initialize class fields.

It is not surprising that with Dart being OO first, they have designed 
their superficially similar features to fit OO use cases.

> which is used to optimize performance (in 
> Dart, `const` is closer to D's `immutable`).

Actually, it is closer to `static immutable`.
Dart `const` means "compile-time constant".

There is also `final`, but it is not transitive.

> The mechanism presented in 
> the link above demonstrates the concept of lazy evaluation while also 
> being compatible with const. The variable is still const, however, the 
> computation of its initial and only value is deferred until its first 
> usage.

I don't understand why you'd want to do that. A const variable has a 
const initializer and it is final. What do you gain from late 
initializing such a variable? Also, Dart designers agree with me to the 
point where you actually can't even do that: "Members can't be declared 
to be both 'const' and 'late'"

(Note that in D you are actually less restricted and can initialize 
immutable globals in a `shared static this` module constructor at 
program startup.)

You can do "late final", but the meaning of that is equivalent to doing 
encapsulation manually with runtime checks like I suggested. Maybe 
create a mixin/mixin template or struct that does the things for you 
that Dart has built-in if you need those. The built-in qualifiers are 
probably not what you want if you need late initialization. I guess an 
alternative would be to create a DIP that adds Dart-like features, but I 
don't know how well that would be received.



More information about the Digitalmars-d mailing list