# How can I better manage memory usage when defining functions?

Suppose I have defined a numerical function F[x] that for each entry x, it takes a long time to calculate.

Suppose that now I want to define a new function using the previous one, say, G[x_] := F[x]^2 + 2*F[x] + 1.

My first question is, does Wolfram Mathematica calculate twice the value of F[x] to use it in G[x]? that is, first calculate the F[x] for F[x]^2 and then the F[x] for the 2*F[x]?

And if this is the case, how could I improve the way I define G[x] so that it only calculates F[x] once?

• You can use memoization to evaluate it only once (F[x_] := F[x] = ...). – user541686 Oct 17 '19 at 10:50

Yes, putting the function call in twice will cause it to be evaluated twice. You can visualize this by putting a Print inside the function, for example:

f[x_] := (Print["In f"]; x)

g[x_] := f[x]^2 + 2*f[x] + 1

g
(* In f *)
(* In f *)
(* 2    *)


You can see that it went to f twice. To avoid that, you can assign a temp variable:

g2[x_] := Module[{t = f[x]}, t^2 + 2*t + 1]

g2
(* In f *)
(* 2    *)


Changing f to something slow, to illustrate the difference in timing:

f[a_] := NIntegrate[{Sin[x + y]/(1 + x^4 + y^4), (Sin[x] + Cos[y])/(
1 + x^4 + y^4)}, {x, 0, \[Infinity]}, {y, 0, \[Infinity]}]

g // AbsoluteTiming
(* {22.6585, {3.56334, 6.79898}} *)
g2 // AbsoluteTiming
(* {11.2694, {3.56334, 6.79898}} *)

• With instead of Module can give additional speed-up. – Alx Oct 17 '19 at 2:12
• @Alx With RepeatedTiming I get exactly the same answer using g3[x_] := With[{t = f[x]}, t^2 + 2*t + 1] and g2[x_] := Module[{t = f[x]}, t^2 + 2*t + 1]. Is there a better way to write it? – MelaGo Oct 17 '19 at 3:23
• I meant general advice to use With as it does just direct replacement and does not create additional variables \$smth like Module. But you are right, in this case there is no difference. – Alx Oct 17 '19 at 4:45
• WOW it never clicked until now! WHAT! This is AN AWESOME ANSWER👏 – CA Trevillian Oct 18 '19 at 23:04
• @CATrevillian Thanks! – MelaGo Oct 19 '19 at 21:26

You could do something like

G[x_] := a^2 + 2 a + 1 /. a -> F[x]


or

G[x_] := #^2 + 2 # + 1 &@F[x]