# Explicit use of Evaluate not behaving the way I expect it to

I discovered a strange behavior of the Evaluate function.

Case 1:

Clear[f]
f[x_] := x^2
g[x_] := Evaluate[D[f[x], x]]
Clear[f]
g[x]

2 x


Case 2:

Clear[f]
f[x_] := x^2
g[x_] := Evaluate[D[f[x], x]] + f[x]
Clear[f]
g[x]

f[x] + Derivative[1][f][x]


I think the Case 2 behavior is strange, because the derivative of f isn't evaluated properly when g defined.

Why do I see this difference?

-
Welcome to Mathematica.SE, thanks for taking the effort to state well formated question :) – Kuba May 15 '14 at 14:17
Thank you for your quick and easy-to-understand reply! – Licht Takeuchi May 15 '14 at 14:22
I feel compelled to ask for the reopening of this question. I do not think it duplicates the question Mr.Wizard identifies as being duplicated. This question is about the explicit use of Evaluate at different levels of an expression and it's interaction with SetDelayed. The other question is about the explicit use of Evaluate and it's interaction with Function. For experienced Mathematica users, the two question are related, so it is no coincidence that part of Mr.Wizard's answer to the other question is applicable to this question. ... – m_goldberg May 16 '14 at 1:28
... But, despite the relationship, I assert that this question is sufficiently different that less experienced users, should they follow the link, will be more confused than enlightened. Should this question be reopened, I suggest the link to the other question be given in a comment. – m_goldberg May 16 '14 at 1:29
@m_goldberg Okay, we'll try it your way. I posted a modified version of my original answer here. I await the community's feedback. – Mr.Wizard May 16 '14 at 3:18

The reason is because Evaluate works only on the first level of held expression. Take a look:

You are using SetDelayed while creating g, it has Attribute HoldAll:

Attributes@SetDelayed

{HoldAll, Protected, SequenceHold}


so effectively, the right hand side of your definition is:

Hold[Evaluate[D[f[x], x]]] // FullForm (*first case*)

Hold[Derivative[1][f][x]]

Hold[Evaluate[D[f[x], x]] + 1] // FullForm (*second case*)

Hold[Plus[Evaluate[D[f[x],x]],1]]


As you can see, in the latter case Evaluate is deeper and is not going to work.

It is quite important issue and, imo, not stressed enough in documentation. You can read about it in PossibleIssues section of Evaluate.

-
It's also mentioned in the Details section. – Sjoerd C. de Vries May 15 '14 at 14:26
@SjoerdC.deVries Agree, but that sentence is quite convolved for new users :) or at least it was for me ;) – Kuba May 15 '14 at 14:34

Kuba explained what went wrong. This example will show you how to get the behavior you were probably expecting. Just use Set ( = ) instead of SetDelayed ( := ). This will get f evaluated at right time and will work for arbitrarily deeply nested calls to f.

Clear[f, g, h, x]
f[x_] := x^2
g[x_] = D[f[x], x] + f[x];
h[x_] = (1 + f[x]^3)/D[Log[f[x]], x];
Clear[f]
{g[x], h[x]}


{2 x + x^2, 1/2 x (1 + x^6)}

-

Evaluate only works when it is the explicit head of an argument. In other words Evaluate[ . . . ] must appear as one of the arguments of the Head who's Hold attribute you wish to override. You should read this paper, which teaches this among many other useful things:

As an example consider these lines:

Hold[1 + 1, Evaluate[2 + 2]]
Hold[1 + 1, {Evaluate[2 + 2]}]
Hold[1 + 1, Evaluate @@ {2 + 2}]

Hold[1 + 1, 4]

Hold[1 + 1, {Evaluate[2 + 2]}]

Hold[1 + 1, Evaluate @@ {2 + 2}]


Note that only the first form evaluates. On lines two and three the Heads of the second arguments are List and Apply rather than Evaluate.

In your example the outer function with a hold Attribute is SetDelayed rather than Hold, but the same logic applies.

A common method to get around this is to use With to inject an expression into the body of the definition:

Clear[f]
f[x_] := x^2

With[{body = D[f[x], x]},
g[x_] := body + f[x]
]

Clear[f]
g[x]

2 x + f[x]


If you want to evaluate the entire right-hand-side, as in your first example, merely use Set instead of SetDelayed, and eliminate Evaluate:

Clear[f, g]
f[x_] := x^2

g[x_] = D[f[x], x];

Clear[f]
g[x]

2 x


(If this answer seems strangely familiar that's because it is; call this an experiment in following the advice to reopen.)

-