Lazily Initialized Variables that are Compatible with const/immutable

Timon Gehr timon.gehr at gmx.ch
Sat Nov 19 00:18:04 UTC 2022


On 18.11.22 18:22, Vijay Nayar wrote:
> On Friday, 18 November 2022 at 11:06:44 UTC, Timon Gehr wrote:
>> On 18.11.22 11:59, Timon Gehr wrote:
>>>
>>>
>>>> which is used to optimize performance (in Dart, `const` is closer to 
>>>> D's `immutable`).
>>>
>>> Actually, it is closer to `static immutable`.
>>
>> (But even that analogy has significant limitations, e.g., transitivity 
>> of Dart `const` is often checked at runtime, even if it is completely 
>> obvious during type checking that an assignment is not going to work.)
> 
> It's not as complicated as you are making it out to be.

I don't understand what you think is complicated. Everything I wrote was 
true. The issue was that in your post you were conflating concepts in D 
and Dart that are only superficially similar.

Anyway, by all means, go ahead and create a DIP for lazy initialization. 
I have proposed this exact thing (with lazy keyword and all) in the 
past, but it never really caught on. (And frankly, it _would_ be 
confusing if for fields "lazy" actually meant lazy while for function 
parameters it still means "by name"...)

> The purpose of Dart's late variables is as they describe:
> 

I am very much aware of the purpose of lazy initialization. It's one 
reason for my recommendation to avoid D's mutability qualifiers if any 
kind of abstraction is involved. The mutability qualifiers break 
abstractions.

Anyway, Dart is not actually providing anything that you can't have in 
D. It does not actually have transitive `const` and `immutable` 
qualifiers. Those are the issue. If you don't use them you can use the 
same patterns as in Dart, just with different syntax.

> ...
> 
> There are many cases where lazy initialization can be used to avoid 
> costly setup, but currently in D, if you use lazy initialization, you 
> must immediately rewrite all your code

Not if you avoided qualifiers. (As I do.)

> and avoid ever using `const`, 

Yes, that was my point. Lazy initialization is not the only common 
pattern that the qualifiers prevent. Don't use them unless you know 
exactly what you are doing and will want to do in the future. (So very 
infrequently or at least in very special circumstances.)

> because it might trigger initialization of lazy variables. This is 
> especially silly for functions like "print" or "writeToDisk", which 
> absolutely do not modify the classes at hand.

That's a weird way to put it because they do actually modify memory 
during late initialization and `const` prevents you from doing it. Don't 
use `const` if that's not what you want. Probably you want what's 
sometimes called "logical const", but that's not a feature in D.

In your OP, you asked the question "Is there another way to perform lazy 
initialization that is compatible with const/immutable, or is this 
needed as a language feature?"

You'd need to change the language to do what you want, but just adding 
built-in support for lazy initialization would not actually fix the more 
general problem. Mutation of memory is often an implementation detail, 
not just for lazy initialization. You'd probably just run into some 
other roadblock further down the line. And any hack you do in your own 
code to work around the strictness of qualifiers leads to undefined 
behavior. It's just not worth the hassle.



More information about the Digitalmars-d mailing list