Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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?

share|improve this question
    
Welcome to Mathematica.SE, thanks for taking the effort to state well formated question :) –  Kuba May 15 at 14:17
    
Thank you for your quick and easy-to-understand reply! –  Licht Takeuchi May 15 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 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 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 at 3:18

3 Answers 3

up vote 6 down vote accepted

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.

share|improve this answer
    
It's also mentioned in the Details section. –  Sjoerd C. de Vries May 15 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 at 14:34

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.)

share|improve this answer

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)}

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.