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.

A few use cases:

(1) This, as expected, returns (almost) immediately:

f[x_?NumericQ] := Evaluate[(Pause[1]; x)]
Plot[f[x], {x, 0, 1}]  

(2) This takes forever:

f[x_?NumericQ] := (Pause[1]; x);
Plot[f[x], {x, 0, 1}, Evaluated -> True]

(3) This is much faster than (1):

f[x_?NumericQ] := {(Pause[1]; x), x x};
Plot[f[x][[1]], {x, 0, 1}, Evaluated -> True]

(4) This returns immediately ... with a "wrong" plot:

f[x_?NumericQ] := {(Pause[a = x + 1]; a), x};
Plot[f[x][[1]], {x, 0, 1}, Evaluated -> True]

(5) While this, as expected, returns immediately, with the "right" plot:

f[x_?NumericQ] := Evaluate[(Pause[a = x + 1]; a)]
Plot[f[x], {x, 0, 1}]

I would like an "authoritative" explanation of cases (3) and (4) ... the rest I think I'm able to understand, but posted for completeness, and to get a complete answer that could be useful for others too.

share|improve this question
add comment

1 Answer 1

up vote 11 down vote accepted

If my understanding of it is correct, the evaluation sequence with Evaluation->True is as follows:

  • As first step, hide all external assignments to the iteration variables, in your case x (probably by using a Block[{x},...] construct).
  • As second step, evaluate the expression without having an assignment to the iteration variables. Remember the resulting expression.
  • As third step, assign values to the iteration variables as needed, and evaluate the expression obtained in the previous step for each value.

In your case (2), the expression with non-numeric x is inert, so the expression evaluated for each value of x is f[x] with numeric x, whose evaluation includes the Pause. That part you probably figured out yourself.

In your case (3), the expression to evaluate is f[x][[1]]. Again, f[x] is inert, so f[x][[1]] gives the first argument of f[x], which is x. So the expression to be evaluated is x, which of course is very fast; there's not even a call to f involved. Now it happens that your function, if called with a numeric value, would have returned a list with the value of x as a first element, so the plot you'd get with evaluating f on a numeric value and taking the first element would be the same. However that is just a coincidence, since your function is not even called.

In your case (4), the very same happens. Only this time you notice the difference, because the first element of the list your function returns no longer happens to be the value of the argument. Note that another way to see that your function has not been called is to evaluate a after the plot. Since your function assigns to a without protecting it with a scoping construct, after calling your function a should have a value of one more than the argument passed to f. However a remains unassigned, showing that your function was never called.

In your cases (1) and (5), the Evaluate only affects how f is defined, not the evaluation of f in Plot. Therefore there are no surprises. Basically, your definition in those cases is almost equivalent to if you had used = instead of := (it is not completely equivalent, but the difference doesn't matter for your code).

share|improve this answer
add comment

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.