Part assignment not compatible with WMA
Description
If two symbols A and B are attached to the same expression expr, and at some point Set is called over a Part of one of them (for example, B[[1,1]]=val), according to the WMA behavior, B should be assigned no a new expression, keeping the value of A untouched. However, in Mathics, we are not checking if expr is shared with another definition, so the change in b produces a change in A too.
How to Reproduce
Consider the following code:
A={{1,2},{3,4}}; B=A; B[[1,1]]=-1; A
in WMA, it returns
{{-1,2},{3,4}}
while in WMA, we get
{{1,2},{3,4}}
Expected behavior
The interpreter should be able to determine if the expression in B is used in another definition, and make a deep copy of the expression in that case.
Your Environment
Mathics 4.1.0.dev0 on CPython 3.8.12 (heads/v2.3.4.1_release:cd8ca63678, Jun 7 2022, 02:05:46) using SymPy 1.8, mpmath 1.2.1, numpy 1.21.4
Priority
Average
I also see that that set_part of parts.py works in a really screwy way.
In general, we have routines like this that change Head in an Expression to change the meaning. When we have a ListExpression (or more generally some other specialized kind of expression) replacing Head isn't going to work because you need to change the entire object.
I am sure all this inline expression munging was done "in the name of efficiency" but it is also a the expense of safety (there can be very subtle bugs when stuff like this is done) and most importantly comprehensibility.
All of this code should be rewritten in a more functional style - return objects rather than modify them in place and making more explicit what is changed.
All of this code should be rewritten in a more functional style - return objects rather than modify them in place and making more explicit what is changed.
If we only had used a persistent/immutable data structure at the start of our projects, it would have made things much simpler
- https://github.com/tobgu/pyrsistent