# Using function within expression

I have an elementary question. I would like to do this:

ex := A B;
asym(_, $A,B$);
Rule := {
x -> @(ex)
};

but without introducing ex as an intermediate. So something like:

Rule := {
x -> @asym($A B$, $A,B$)
};

I'm sure there must be a way to do it in Cadabra 2 but I cannot figure it out... Probably some python knowledge is needed!

+1 vote

Not possible at the moment. The @ operator which pulls a Python expression into a maths expression does not do any evaluation. It would be nice to be able to write

Rule := {
x -> @{ anything python that produces an Ex }
};

but at the moment that does not exist.

by (66.3k points)

Thanks for the answer! I was driving myself nuts trying to figure out how to do it... ;-)

With the version currently on github, you can enable experimental function evaluation using

kernel(call_embedded_python_functions=True)

You can then do

Rule:= { x -> asym( A B, {A,B} ) };

to get

Rule:= x -> 1/2 A B - 1/2 B A;

Please be aware that this is experimental. You can use any Python function here, including the ones that you define yourself. The arguments you will receive are always Ex objects (so the A B and {A, B} above are passed to asym as two Ex objects, as required).

Note that the interface may change in the future because there may be unwanted side effects which I haven't yet grasped. (For instance, any function that is known on the python side will now get called, whether you want it or not. So if you were in the habit of writing sin(x) in Cadabra expressions, instead of \sin(x), then turning this option on will produce an error, because Python's sin function does not accept Ex objects).

Feedback (more than) welcome.

by (66.3k points)

Hi Kasper,

I've found a bug in the above implementation. (Using current github version.)

The below works appropriately:

$V_{a} W_{b}$;
substitute(_, $V_{a} W_{b} -> V_{a} W_{b} + c1 asym(V_{a} W_{b},{_{a},_{b}})$);

However, if I replace c1 with an explicit number (or a sign), it pretends the number (or sign) is +1.

$V_{a} W_{b}$;
substitute(_, $V_{a} W_{b} -> V_{a} W_{b} + 27 asym(V_{a} W_{b},{_{a},_{b}})$);

The above evaluates as if 27=1.

Thanks, now fixed.