There are functional languages that do this. Like many other optimizations, you get less than your intuition might naturally expect, but it does work.
A trivial case is "tail call optimization", which most immediately involves not creating a literal in-memory stack record for recursive invocations but also can easily involve the compiler re-using the memory for the arguments. IIRC Erlang will do that as much as it can in tight recursive calls.
Erlang/BEAM fits your hypothetical to some degree. Erlang the language has immutable variables; however, BEAM, the virtual machine, has mutable registers. Whether or not a given code sample results in copy or mutation depends on what information is available to the compiler, of course.
I was doing something similar for SQLAlchemy recently. SQLAlchemy is all about capturing Python operators and operands into data structures that represent intent which can be invoked later.
edit: here is a demonstration: https://gist.github.com/zzzeek/caa4a7ed94f326fbbc031acecb9d7...
edit edit: it is actually possible with numpy by using the Dask library: https://dask.org/
i can say for my side of things thunking is a super huge performance gain as it allows for quick gathering of expression intent and then the computation side on the other side of a cache.
Accelerate is a nice example of an array library with a JIT backend.
I don’t know the state of NumPy on PyPy since I don’t use PyPy.
I'm not sure if it's doing inlining before the laziness analysis, which would be ideal.
[1]: https://pythran.readthedocs.io/en/latest/INTERNAL.html#lazyn...
You could imagine some hypothetical language in which all objects are immutable, as far as the programmer is concerned - however the compiler is allowed to reuse objects behind the scenes if there is provably no way that a side-effect could be introduced.
E.g., in such a language, the first variant would be the only legal form to write the normalizing function:
However, this could be safely turned into the following during compilation: ... because array2 is not visible outside the function and therefore could not cause side-effects.