In my version of object-oriented programming in Mathematica, essentially (without going into details)
obj[a] is a reference to an object whose actual data is stored inside
data[a]. Methods like
obj[a][function] then use and/or modify that data.
Schematically, I define addition of objects using UpValues as follows:
obj[a_] + obj[b_] ^:= add[a, b];
add function looks at the values stored in
data[b], combines them in the desired way, and then stores them in
ui is a new unique identifier (with
i an integer) and returns
Now, here is my problem. Consider a long chain of additions, e.g.
obj[a] + obj[b] + obj[c] + obj[d]
This creates 3 new objects in total,
obj[u3], since each addition of two objects creates a new object. Schematically:
obj[a] + obj[b] + obj[c] + obj[d] = obj[u1] + obj[c] + obj[d] = obj[u1] + obj[u2] = obj[u3]
If many objects are added, this creates an abundance of new objects that I don't need. After the addition is over, I would like to clear all of them except the last one, which is the actual result of the expression.
Just clearing all of the
i less than the current index every time I add two objects won't work, for two reasons:
- Older intermediate steps are still in general needed for the next steps. For example, In the addition I showed above, if the addition
obj[c] + obj[d], which results in
obj[u1], then I won't be able to add
obj[u1] + obj[u2]to produce
- If I perform another (separate) addition later, then I don't want it to delete the results of the previous addition.
Therefore, I need to somehow know where the instance of
add[a, b] that is currently running is located in the chain: is it the first, the last, or an intermediate step. If it's the first, I mark the current
i as the beginning of the objects to delete. If it's the last, then I delete all of the objects created from that point until
i - 1 where
i is the current step.
A simpler option is just to know that the instance is the last step, and then rename the object to something like
vi is a new unique identifier and delete all of the
Is that possible? If not, what are some other ways in which I can avoid keeping all the objects that were created in the intermediate steps?
I am also doing something similar with multiplication, i.e.
obj[a_] * obj[b_] ^:= multiply[a, b], so the solution will need to incorporate combinations like
obj[a] + obj[b]*obj[c], which significantly complicates things.
The solution I am currently considering is to have the user enclose any operation with some kind of wrapper (e.g.
cleanup[ obj[a] + obj[b]*obj[c] ]) and have
cleanup rename its argument to
obj[vi] and delete all the existing intermediate steps
obj[ui]. This makes the syntax slightly less elegant for the user, but doesn't require any complicated pattern matching.
It would be nice if there was some way to have the wrapper execute automatically when a cell ends its evaluation, or something like that, in which case the user won't have to worry about the wrapper whenever they make an addition/multiplication operation.