# Evaluation control in function definition: Total interferes with Evaluate

Here is a simple example to illustrate my problem:

expr = {a + b*Exp[-r t], a - b*Exp[-r t]}
(* {a + b E^(-r t), a - b E^(-r t)} *)

g[t_, b_] := Total[Evaluate[expr], {2}]

g[10, {b1, b2}]
(* {a + b E^(-r t), a - b E^(-r t)} *)


It looks is like Total[] undoes the Evaluate[] statement. Indeed:

g[10, 1]
(* {a + b E^(-r t), a - b E^(-r t)} *)


What I wanted and expected was the same output as when doing

h[t_, b_] := Evaluate[expr]

Total[h[10, {b1, b2}], {2}]
(* {2 a + b1 E^(-10 r) + b2 E^(-10 r),
2 a - b1 E^(-10 r) - b2 E^(-10 r)} *)


I would like to understand why it can't be done the way I did, and how to do it instead (in the function definition). I am using Mathematica 13.3 on Windows.

• To make your test cases a bit simpler, look at : expr = x; f1[x_] := expr; f2[x_] := Evaluate[expr]; f3[x_] := f4[Evaluate[expr]]; {f1[0], f2[0], f3[0]} Commented Oct 12, 2023 at 15:17
• Right. I get {x, 0, f4[x]}, and it is the last output I don't understand. Commented Oct 12, 2023 at 15:20
• Actually, it is the second output that should pop-out to you :) You may want to look at Definition[f1], Definition[f2] and Definition[f3]. You will see that in f2, expr evaluated to x already at the time you defined the function, while in the other two cases, expr remained intact, as expected. x in expr will then not be automatically replaced with the function argument x! There are various solutions, for example: g[t_, bb_] := Total[expr /. b -> bb, {2}] or Clear[expr]; expr[b_] := {a + b*Exp[-r t], a - b*Exp[-r t]}; g[t_, b_] := Total[expr[b], {2}] Commented Oct 12, 2023 at 15:27
• No, that is precisely why first and second do not pop out to me. They gave what I expected. For example for f2, the defining statement is already equivalent to f2[x_]: = x at the outset, so it is clear that f2[0]=0. I would have thought that in the same way, the definition for f3 is f3[x]:=f4[x], since I asked for the inside of f4 to be evaluated immediately. But as Bob Hanlon says below, it appears Evaluate is buried too deeply - which IMO somewhat defeats the purpose of it. Commented Oct 12, 2023 at 15:42
• If you read the documentation for Evaluate, it states "Evaluate works only on the first level, directly inside a held function". This seems perfectly reasonable to me, because otherwise the evaluation process would need to parse the expression tree entirely looking for any Evaluates before moving on. Commented Oct 12, 2023 at 16:16

\$Version

(* "13.3.1 for Mac OS X ARM (64-bit) (July 24, 2023)" *)

Clear["Global*"]

expr = {a + b*Exp[-r t], a - b*Exp[-r t]};

g[t_, b_] := Total[Evaluate[expr], {2}]


The Evaluate is buried too deep to be evaluated when g is defined

?g


Consequently, the b and t in expr are not the same as the localized b and t in the subsequent evaluation of g. You would need

g[t2_, b2_] := Total[Evaluate[expr /. {t -> t2, b -> b2}], {2}]

?g


g[10, {b1, b2}]

(* {2 a + b1 E^(-10 r) + b2 E^(-10 r), 2 a - b1 E^(-10 r) - b2 E^(-10 r)} *)


But then the Evaluate is not necessary.

Clear[g]

g[t2_, b2_] := Total[expr /. {t -> t2, b -> b2}, {2}]

g[10, {b1, b2}]

(* {2 a + b1 E^(-10 r) + b2 E^(-10 r), 2 a - b1 E^(-10 r) - b2 E^(-10 r)} *)
`