# Evaluating part of an expression, but delaying the rest

Say I have an expression

g = x^2 + y^3;


I tried writing this

H[x_, y_] := Eigenvalues[Evaluate[{{0, g}, {g, 0}}]];


The behaviour I am trying to achieve is that when I write H[2,3] it will substitute x->2 and y->3 inside the matrix and then evaluate Eigenvalues. I do not want Eigenvalues to be evaluated before calling H[x,y] because in general it is much more efficient to calculate the numerical eigenvalues rather than symbolic and then substituting. How can I achieve this behaviour? I don't want to do something ugly like

H[xx_, yy_] := Eigenvalues[{{0, g}, {g, 0}} /. {x -> xx, y -> yy}]


I would like to keep using the same variable names in an intuitive way

• Your examples don't evaluate as you desire, or at all, rather, in that the x and y inputs are not passed to the defined g function. I think if g were defined differently, you might be able to better tackle this problem. May 15, 2020 at 14:53

Why not use function?

ClearAll[g, x, y, H];
g[x_, y_] := x^2 + y^3;
H[x_, y_] := Eigenvalues[{{0, g[x, y]}, {g[x, y], 0}}]


And now

H[2, 3]


gives

(-31,31}


And to avoid having to call g[x,y] twice, you could optimize it a little

ClearAll[g, x, y, H];
g[x_, y_] := x^2 + y^3;
H[x_, y_] := Module[{z = g[x, y]}, Eigenvalues[{{0, z}, {z, 0}}]]


it is possible that Mathematica is smart enough in the first case to do this for you automatically, i.e. evaluate g once, but if not sure, you could do the above and make it more explicit.

• Thank you :) Although I would prefer not to define g in this way. Just because in my code I have functions that depend on functions that depend on functions down several layers. And I prefer not having to decide what is a local variable and a global variable until the point I construct some high level function like H[x_,y_]
– Tom
May 13, 2020 at 16:24
• @Tom I think, then, regarding your want to not decide what is global and local etc until you define H would be better achieved by using a method like Nasser’s here. You have already made the decision to treat x and y as global once you defined g in the way you did. If that is the way you wish to start your definitions, it is my understanding you are no longer waiting to decide what is global and what is local etc. May 15, 2020 at 14:25

These options might suit your needs, but I don't expect you can achieve what you wish by defining g with global variables initially as you have in your question.

ClearAll[g, H, Hw];
g = #1^2 + #2^3 &;
H[x_, y_] := Eigenvalues[{{0, g[x, y]}, {g[x, y], 0}}];
Hw[x_, y_] := With[{g = g[x, y]}, Eigenvalues[{{0, g}, {g, 0}}]];


Both of these have a length of 5 for their trace, which is the same as Nasser's first example (the second carries length 6).

Actually I guess this does what you want, but it is excruciatingly messy and confusing, however, it does use the same variable definitions of x and y, global definition of g, and doesn't evaluate Eigenvalues until the internal expression is completely evaluated...

ClearAll[g, x, y, h];
g = x^2 + y^3;
h[x_, y_] :=
Eigenvalues[{{0, # /. {Defer[#][][][] -> x,
Defer[#][][][] ->
y}}, {# /. {Defer[#][][][] -> x,
Defer[#][][][] -> y}, 0}}] &@g;


The length of the trace is 8, however...

• Not quite sure how to make it robust against the redefinition of the variables though. May 15, 2020 at 18:33