I've seen some posts about mutable objects in WL and some implementations:
- Once more on object orientation in Mathematica: does it have to be so hard?
- Immutability, Association and typing
- Code Readability and Object-Oriented Code
Many of these questions are about OOP or some class inheritance framework for dealing with objects. My question is simpler. Is there a performant and simple way to define an object that can be mutated? No classes, no methods, etc.
The closest thing that comes to my mind are Associations that are stored in a variable:
In[]:= assoc = <|"AC" -> 0, "RAM" -> {0, 0, 0, 0}|>;
In[]:= assoc["AC"] = 4
Out[]= 4
In[]:= assoc
Out[]= <|"AC" -> 4, "RAM" -> {0, 0, 0, 0}|>
x["key"] = val
is what I want to see in my code.
The problem with the above association is the following:
In[]:= assoc["RAM"][[1]] = 4
During evaluation of In[]:= Set::setps: assoc[RAM] in the part assignment is not a symbol.
Out[]= 4
I understand why that fails, but to me there should be a way to write code like that.
I know there are mutation handlers that I could use to somewhat make it work (https://mathematica.stackexchange.com/a/165910/59240), but the thing about associations is that they are as fast as WL will go, and I want that performance.
I tried DataStructure
s, the problem is that the code becomes less readable:
In[]:=
assoc2 = <|"AC" -> CreateDataStructure["Counter", 0], "RAM" -> CreateDataStructure["FixedArray", {0, 0, 0, 0}]|>;
In[]:= assoc2["AC"]["Set", 4]
Out[]= 4
In[]:= assoc2["RAM"]["SetPart", 1, 4]
Out[]= 4
Of course that is up to debate. Perhaps the solution is that Set
should work on DataStructure["Counter", ...]
and Set
+ Part
on "FixedArray"
, e.g. assoc2["RAM"][[1]] = 4
.
Another issue when dealing with DataStructure
s is how they interact with Dynamic
and the Front End:
In[]:= counter = CreateDataStructure["Counter", 0];
In[]:= Dynamic[counter["Visualization"]]
(* Out[]= <- Graphics -> *)
In[]:= counter["PreIncrement"]
Out[]= 1
The visualization won't update because the FE has no idea if the contents of the DS changed. There might be ways to overcome this but all seem overcomplicated.
There might not be a definite answer, but hopefully some ideas can be shared.
Thanks
Edit 1:
This works :) :
In[]:= assoc[["RAM", 1]] = 4
Out[]= 4
a=<|"a" -> 0, "b" -> {0, 0, 0, 0}|>;a[["b", 1]]=2;a
$\endgroup$AssociateTo[assoc, "AC" -> 4]
. $\endgroup$