Welcome to Cadabra Q&A, where you can ask questions and receive answers from other members of the community.
+2 votes

Hi,

Im starting to use cadabra 2x (I have alredy used cadabra 1x several times). I have a simple question. How can I call back an expression that I defined previously? for example:

{m,n,p,q,r}::Indices(position=free); 
\nabla{#}::Derivative; 
\partial{#}::PartialDerivative; 
A_{m n}::AntiSymmetric; 
V_{m}::Depends(\partial{#});
ex:=\partial_{m}{V_{n} A_{m}} + \partial_{m}{A_{n m}}:
unwrap(_);

gives as output: A_{m}\partial_{m}{ V_{n} }. But if in a next line I want to define

ex2:=@(ex); 

then, it doesnt return the original "ex" but the last output: A_{m}\partial_{m}{ V_{n} }. Im used to the old ex2:=@[ex] or ex2:=@(%). This last one saves the last output into a new expression, which I dont know how to do it neither.

Thank you!

ps: it seems that \partial_{m}{ V_{n} }, \partial_{m}{V_{n}}, \partial_{m}( V_{n} ) or \partial_{m}(V_{n}) work in the same way. Is this correct ? (note the difference in changing spaces and brackets).

in General questions by

1 Answer

+1 vote

Cadabra's algorithms (in both version 1.x and 2.x) act 'in-place', that is to say, they modify the original expression. This is in contrast to many other computer algebra systems, which leave the original expression unmodified, but return a new expression (which, in terms of your example, you then have to assign explicitly to ex if you want ex to contain the 'current state').

So if you want to preserve the initial form of ex, you need to make a copy before you start modifying it; something along the lines of

{m,n,p,q,r}::Indices(position=free); 
\nabla{#}::Derivative; 
\partial{#}::PartialDerivative; 
A_{m n}::AntiSymmetric; 
V_{m}::Depends(\partial{#});
orig:=\partial_{m}{V_{n} A_{m}} + \partial_{m}{A_{n m}}:
ex:=@(orig):
unwrap(_);

and then

ex2:=@(orig);

to get another copy of the original expression.

The _ symbol refers to 'the last expression that was modified', not 'the thing returned by the last function call'.

There are advantages and disadvantages of both approaches ('in-place' and 'functional'). Cadabra historically (and for very good reasons) used 'act in place' operations, and even if I wanted to (which I don't), it's too late to change that now.

(For completeness: note that ex:=@(orig) is a Cadabra-style assignment, not a Python assignment. That is to say, when Cadabra encounters a @(...) expression, it always makes a copy of the .... Contrast this with the Python assignment

ex=orig

which would simply give an additional name ex to the orig expression; acting on this ex would also modify the expression pointed to by orig. Both ex and orig are handles (references) to the same expression object in this case).

by (76.7k points)
...