6
$\begingroup$

My colleague sent me this surprising example of code today (this is after stripping everything unrelated to the evaluation):

Plot[ Evaluate[ ( x -  1) /. { x -> y}] /. i -> 1 , { x , 0 , 1}]

Note that the last substitution {i -> 1} is done outside of Evaluate.

Naively I expected this to produce an empty plot since the substitution replaces the plotting variable. However, the plot appears as if there is no substitution:

Plot produced despite the substitution

Whenever Evaluate is wrapped around the entire first argument of Plot, or the function inside Evaluate is simplified, the plot is empty as I expected. Both

Plot[ Evaluate[ x /. x -> y ] /. i -> 1, { x, 0, 1}] (* and *)
Plot[ Evaluate[ x-1 /. x -> y /. i -> 1], {x, 0, 1}]

produce empty plots.

Update: the last substitution {i->1} wraps Evaluate inside ReplaceAll which effectively cancels its action.

One question remains, why is the substitution /. {x -> y} ignored? E.g.

Plot[ (x - 1 ) /. { x -> y} , { x, 0, 1}]

produces a plot of x - 1, but

Plot[ x /. { x -> y}, {x, 0, 1}]

produces an empty plot.

$\endgroup$

1 Answer 1

7
$\begingroup$

Evaluate only does something when it appears directly as a head inside a head with a Hold-type attribute. Otherwise it does nothing. Compare:

Hold[Evaluate[(x - 1) /. {x -> y}]]
Hold[Evaluate[(x - 1) /. {x -> y}] /. i -> 1]

So the short answer is: your use-case of Plot (which is HoldAll) is simply exactly the same as if Evaluate wasn't there at all. I'm not quite sure why you're using the rule i -> 1, though, because there isn't an i anywhere.

Edit

There is now a new question about why the following two behave different:

Plot[(x-1) /. { x -> y} , { x, 0, 1}]
Plot[x /. {x -> y}, {x, 0, 1}]

The outlier here is the first line, because it unexpectedly doesn't yield an empty plot. Frankly, I'm not sure what's going on with that. If you wrap the 1st argument in Evaluate, it correctly returns an empty plot, so I'm guessing that Plot has some special rules related to evaluating its 1st argument and somehow that produces this result. I'd call it a bug.

Edit 2

Lucas Lang explained this correctly in the comment. It's the same as this:

x = 1;
x - 1 /. {x -> y}
x /. {x -> y}
$\endgroup$
3
  • $\begingroup$ Thanks, indeed I could leave Evaluate out for my minimal example. However, I don't think this fully answers my question, please see the update. $\endgroup$
    – And R
    Commented Apr 10 at 11:12
  • $\begingroup$ In the original expression, the rule i->1 was not so unrelated to the previous expression, however, after some experimentation, I noticed that the content of this rule does not matter: apparently any rule will wrap Evaluate in an expression with a different head. $\endgroup$
    – And R
    Commented Apr 10 at 11:15
  • 2
    $\begingroup$ The reason the first line of the last example gives a non-empty plot is that x is replaced by a number before the replacement happens (at least when ignoring any symbolic preprocessing done by Plot). For e.g. x=0.0, the first expression is (0.0-1) /. 0.0 -> y -> -1.0 /. 0.0 -> y, which fails to replace anything. The second expression on the other hand gives 0.0 /. 0.0 -> y, which does perform the replacement $\endgroup$
    – Lukas Lang
    Commented Apr 11 at 12:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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