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];
The add
function looks at the values stored in data[a]
and data[b]
, combines them in the desired way, and then stores them in data[ui]
where ui
is a new unique identifier (with i
an integer) and returns obj[ui]
.
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[u1]
, obj[u2]
, and 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 obj[ui]
for 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 inobj[u2]
, clearsobj[u1]
, then I won't be able to addobj[u1] + obj[u2]
to produceobj[u3]
. - 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 obj[vi]
where vi
is a new unique identifier and delete all of the obj[ui]
.
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?
EDIT 1:
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.
EDIT 2:
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.