vvvv / VL-Language

The official repo for the design of the VL programming language
31 stars 0 forks source link

[Quest] Flavors of Immutability #48

Open gregsn opened 2 years ago

gregsn commented 2 years ago

Introduction

What is Immutability?

Immutable objects don't change. Calling SetFoo on an immutable object will return a new snapshot.

Flavours we can distinguish when looking at object graphs

That's where the explanation part slowly comes to an end and the quest part starts.

Some History

Back in the day, we intuitively were focussing on deep immutability. For example, we were stating: a Spread<T> is an immutable collection, which also means that T must be immutable. (The type inference was actually attaching a constraint to that T so that it only can be replaced by an immutable type later on.) So we interpreted the fact that Spread<> is immutable in a way that the application, e.g. Spread<Integer32> also has to be immutable. But that would exclude certain applications. Shall we really not allow Spread<object>? We should allow that. But is that type application immutable? Well. It is flat immutable, but not deep immutable.

When you have AsyncLoop. Should you be allowed to link a Spread<object> into that region running on a different thread? Some of those objects might mutate. So it's not thread-safe... In the early days, we tried to make sure that the type inference always makes sure that deep immutability is guaranteed where it is needed (e.g. on that link going into a delegate or higher-order region, since this might get executed on a different thread).

But while we were progressing, we also found out that when choosing Record you still want to be able to refer to mutable objects sometimes. You actually want to have a snapshot-based / copy-on-write / immutable behavior, BUT just on that level, not all the way "down". You might even want to be able to use process nodes that mutate. See the Syncer inside of SkiaPaint as an example. And you might want to be able to store mutable objects inside fields.

You still might want to have warnings, but no errors. So we learned that we have to allow more and more.

Process patches

When choosing Process you are saying that you don't want to decide really. You are actually saying: when the resulting process node is used inside a record definition, then please just adapt and also act as a record. This again comes from the desire to have deep immutable behavior whenever possible. Choosing Process could also be coined AdaptToContext regarding immutability. The fact that we don't allow a State Output here is due to the fact that we don't know how the process node will be used. Some instances of that Process will actually be initialized in a way that they act immutable, others will act mutable.

Interfaces

Interfaces currently don't have the notion of immutability. They can act as an interface for both immutable and immutable implementations. There were ideas of having also immutable interface definitions that then would guarantee that every implementation also has to be immutable...

The quest

some questions for which a precise answer would be nice:

So there are quite some interconnected quests. We of course have ideas regarding all those questions and some tendency. But let's try to come up with 2 or 3 attempts at solving the quests and see which proposal shines the brightest.

Please also feel free to add questions or comments to the quest.