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 DataStructures, 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 DataStructures 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– M.R. Sep 29 '21 at 03:17AssociateTo[assoc, "AC" -> 4]. – Rohit Namjoshi Sep 29 '21 at 13:12