Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Immutable design #2017

Open
plajjan opened this issue Dec 9, 2024 · 2 comments
Open

Immutable design #2017

plajjan opened this issue Dec 9, 2024 · 2 comments

Comments

@plajjan
Copy link
Contributor

plajjan commented Dec 9, 2024

No description provided.

@plajjan
Copy link
Contributor Author

plajjan commented Dec 9, 2024

Does assignment vs inner mutability matter?

I have a netconf client actor that keeps track of module capabilities for a device. This is stored in Client.modules. I think this data structure should be immutable since once it is created (after we initialize the connection) it never changes. If we send it to someone else (someone interested in the capabilities of the device), then if it is immutable, we can send a pointer and not an actual copy.

However, a client can reconnect, in which case the capabilities are replaced, so we need var modules on the Client itself, i.e. a mutable reference, but the thing it references is inner immutable.

@nordlander
Copy link
Contributor

nordlander commented Dec 9, 2024

A very good example of how assignment differs from (inner) mutation. I don't think we've reached a good conclusion yet of what the var keyword should imply (reassignments, of course, but does it also enable or enforce mutability of the data structure denoted by such a variable?).

As long as 'someone else' is another actor the case is a bit clearer -- here we've always assumed that data structures are frozen (i.e., made immutable) because of the message transfer. The open issues are perhaps more about when the compiler can avoid cloning as part of the freezing process, and what the exact relation between mutable classes and their immutable counterparts should be.

However, assuming frozen mirrors of common data structures are in place, there is indeed a technically straightforward approach available that resolves the general issue: let var enable reassignments only and let the question of mutability be handled by the type system. So var x : frozendict[A,B] would then be the way to introduce a variable that can be reassigned but not mutated, while x : dict[A,B] would indicate a constant reference (a structure whose location/identity never changes) to memory that can be mutated. The latter must of course never occur in an actor interface, but this is already controlled by our existing requirement that actor interfaces are _ sealed_ (well, this check is currently turned off while we wait for frozen classes to arrive, but that's the idea, anyway). The combinations var x : dict[A,B] and x : frozendict[A,B] are of course also available.

A good thing with this approach is that it doesn't oversimplify the underlying issue, and it works well with type inference. This means that the choice between a mutable or immutable data structure x can be inferred from the presence/absence of statements that mutate x; if x is ever updated at some key then it must be a ´dict´, otherwise it can be a frozendict (or whatever we want to call it). And if the programmer really wants to state the intended use of x (decoupled from its actual use), a simple type signature is sufficient.

The only drawback I can see with this approach is that it really requires the programmer to understand the difference between reassignment and mutation. And that is maybe a bit much to ask, at least from newbies. It's the x : dict[A,B] case that's particularly confusing, I think. So maybe a variant could be to require the var keyword in front of every variable of mutable type... But can such an idea be extended to also work for function arguments, without radically changing the flavor of the language? I really don't know...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants