I am looking for advice on implementing the following. (It is possible that the answer is that it is simply not a good idea to do this.)
I would like to have an object similar to FittedModel
. Let's call its head Obj
.
Like FittedModel
, it will have properties, e.g.
properties = {42}; (* properties stored here for the sake of this toy example *)
Obj[id_]["Property"] := properties[[id]]
Now let's define obj = Obj[1]
and evaluating obj["Property"]
will yield 42
.
I am looking to make it possible to do obj["Property"] = 137
to set this property.
Here's an attempt that doesn't quite work (let's ignore SetDelayed
for now and stick to Set
):
Obj /: (Obj[id_]["Property"] = value_) := setObjProperty[id, value]
setObjProperty[id_, value_] := properties[[id]] = value
Now Obj[1]["Property"] = 137
will work as I want it to.
However, obj["Property"] = 256
will not. Instead of changing the property, it will associate the following definition with Obj
: Obj[1]["Property"] = 256
.
Question: Is there a way to implement this syntax for property setting in a reliable way? I realize that this isn't exactly in the spirit of Mathematica objects being immutable. In my case Obj
represents a data structure implemented in C++ and id
is a handle to it.
Note the following behaviour of =
and :=
:
The head of the expression to be set is evaluated by Set
(or SetDelayed
).
Graph
has settable properties which are handled through SetProperty
, PropertyValue
, etc. I find this syntax very tedious, so I was looking for something simpler.
For my application having mutable state seems very natural, and I think it's not worth avoiding. I have a simulation that has a complex internal state, not fully exposed to Mathematica. The simulation can be stopped and resumed. Parameters can be adjusted when the simulation is stopped.
I think (I may be wrong) that in order to work only with immutable objects, in the natural Mathematica way, it would be necessary to expose the full simulation state to Mathematica and to store it as a pure Mathematica expression (instead of data on the C side). I would then store the full state as an Association
, and have a function that runs the simulation and returns a new Association
(simulation state), along with data collected during the simulation process. Associations would also give me this easy property-setting syntax for free.
However, exposing the full state may not be worth all the extra work.