5
$\begingroup$

after reading some related materials(Why do I have to put Evaluate[] here), in my understanding, BecauseAttributes[Plot] has HoldAll, so Plot[Evaluate[Table[a*x^2,{a,1,5}]],{x,-1,1}] should have a Evaluate[] there, but when i remove Evaluate[] before Table[], correct picture still can be drawn. this confused me.

For detailed questions, plz see the comments in the image below. But I'd better write it again:

  1. Why Table[] & Plot[] both have HoldAll, but Table[] must add Evaluate[] while Plot[] is no need to in this case?
  2. Why outputs of Plot[] with Evaluate[] and without differs slightly?

enter image description here

enter image description here


code for tests:

(*case 1*)
Attributes[Table]

p={a,1,5};
Table[a*x,p] (*failed as i think*)
Table[a*x,Evaluate[p]] (*succeed as i think*)

(*case 2*)
Attributes[Plot]

q={x,-1,1}
Plot[x,q] (* no problem but why Evaluate[] before q is not neccessary? *)
Plot[Table[a*x,{a,1,3}],q] (* no problem but why Evaluate[] before Table[] is not neccessary? *)

Plot[Evaluate[Table[a*x,{a,1,3}]],q] 
(*Why here have a color difference while not in the before ?
What causes the slight difference in the output?*)
$\endgroup$
7
  • 3
    $\begingroup$ HoldAll prevents evaluation of arguments at the time of the function call. What happens after that point is up to the function that is called. It can evaluate its arguments if it wants to. Plot[] checks some of its arguments in particular ways, which have evolved over time. So do some of the other numerical solvers. The details are complicated and probably not fully known to non-developers. $\endgroup$
    – Michael E2
    Jan 14, 2023 at 15:54
  • 1
    $\begingroup$ Related: mathematica.stackexchange.com/questions/1731/… $\endgroup$
    – Michael E2
    Jan 14, 2023 at 17:26
  • 1
    $\begingroup$ Please include the code text in your question so we can easily test. $\endgroup$
    – xzczd
    Jan 15, 2023 at 4:23
  • 1
    $\begingroup$ And, if it was 10 years ago, you wouldn't have the first question: mathematica.stackexchange.com/q/2414/1871 mathematica.stackexchange.com/q/20718/1871 Not sure when this feature is added, though. (It's not in v9, but already in v12.3. ) $\endgroup$
    – xzczd
    Jan 15, 2023 at 5:04
  • 1
    $\begingroup$ We can check that in v.13.2 in GeneralUtilitiesPrintDefinitions@Plot` there is option Evaluated -> Automatic. Instead of this Mr.Wizard has recommended Evaluated -> True. $\endgroup$ Jan 15, 2023 at 7:11

1 Answer 1

11
$\begingroup$

I thought this Q&A might be closed as too broad or needing input from WRI. But it's still open with no close votes. I suppose I can explain two things, which might provide the understanding why Table and Plot are different: (1) The purpose of HoldAll (in these functions) and (2) why what Plot does isn't needed in Table (in almost all cases).

The purpose of HoldAll

The purpose of HoldAll in Table[] and Plot[] is primarily to keep the symbolic expressions passed as arguments in their original forms, so that numerical definitions for the symbols in the expressions are not substituted.

For instance, without HoldAll:

foo[x^2, {x, 0, 2}]
(*  foo[x^2, {x, 0, 2}]  <-- good syntax for Plot/Table *)

(* BUT: *)
x = 3.4;
foo[x^2, {x, 0, 2}]
(*  foo[11.56, {3.4, 0, 2}]  <-- bad syntax for Plot/Table *)

In the case where foo is Plot or Table, the user does not usually want to worry about whether the variable they wish to use has been defined during their current session. While the user could be required to clear the value of x before calling Table[] or Plot[], this would be inconvenient. (Using Block[{x}, Plot[...]] instead of Clear[x] is still quite inconvenient.) So Table[] and Plot[] have been programmed to do this automatically for the user without destroying any value(s) that might be assigned to x.

Why Plot[] differs from Table[]

The answer centers on when to evaluate the first argument, the function(s) to be plotted or "tabled." Many things can be handled by all the functions in Mathematica that control evaluation: Evaluate, Unevaluated. HoldAll, HoldAllComplete, etc.

In the case of Table[], there is no common use case in which the first argument of Table[] needs to be evaluated before Table[] is normally ready to evaluate it. The most common case would probably :) be the use of random functions like RandomReal[], which is discussed in the docs (e.g Table[RandomReal[], {5}] gives five different numbers while Table[Evaluate@RandomReal[], {5}] gives the same number five times.

Plot[] has evolved to handle various use-cases commonly encountered by users. It's hard to remember all the changes over the years. Now, Plot[] needs to evaluate the first argument both symbolically and numerically. It analyzes the discontinuities of the function(s) before trying to numerically plot them. It seems to distinguish a vector-valued function from a list of functions and handle these differently. Perhaps to do this, it numerically evaluates the functions before starting to plot them. It also seems to check both the unevaluated argument and the evaluated argument to distinguish these cases. The details are hidden internally, and I cannot be precise about the decision algorithm.

These considerations point to three distinct times at which the funcs argument of Plot[funcs, {x, 0, 1}] might be evaluated:

  1. Before the call to Plot, e.g. Plot[Evaluate@funcs, {x, 0, 1}], which substitutes the value of x if any (usually a disaster): both the argument and the symbolic analysis is made on the value of funcs with x not blocked.
  2. After the call to Plot but before symbolic analysis begins, e.g. Plot[funcs, {x, 0, 1}, Evaluated -> True]: both the argument and the symbolic analysis is made on the value of funcs but with the value of x blocked.
  3. After the call and symbolic analysis, that is, what the normal call Plot[funcs, {x, 0, 1}] does: the argument is literally funcs and the symbolic analysis depends both on literal form of funcs and the value of funcs (with the value of x blocked).

Examples: By "colored", I mean that Plot styles independent functions with different colors. By "uniform," I mean each curve has the same color. If you have an old version of Mathematica, you may find that some plots that are colored in V13 are uniform in your version. (I cannot detail when the version changes occurred.)

Plot[{Sin[x], Cos[x]}, {x, 0, 10}] (* colored *)

funcs = {Sin[x], Cos[x]}; (* list of scalar function *)
Plot[funcs, {x, 0, 10}] (* colored *)

funcs2[] := {Sin[x], Cos[x]}; (* list of scalar function *)
Plot[funcs2[], {x, 0, 10}]    (* colored *)

funcs3[x_] := {Sin[x], Cos[x]}; (* vector-valued function *)
Plot[funcs3[x], {x, 0, 10}]     (* uniform *)
Plot[funcs3[x], {x, 0, 10}, Evaluated -> True] (* colored *)

funcs4[x_?NumericQ] := {Sin[x], Cos[x]};  (* vector-valued function *)
Plot[funcs4[x], {x, 0, 10}, Evaluated -> True] (* uniform *)
(*  colored pairs of uniformly colored vector components: *)
Plot[{funcs4[x], -funcs4[x]}, {x, 0, 10}, Evaluated -> True] 

The last example might need further explanation. Because of ?NumericQ, funcs4[x] evaluates to funcs4[x] if x is not numeric. It numerically evaluates to a list of two real numbers. So it is treated as a vector-valued function. The plot argument, therefore, is a list of vector-valued functions. The first function gets one color, the second gets another color. The components of each function get the same color. This is undocumented, AFAIK, and these are my inferences from observed behavior.

As for the others, apparently: funcs and funcs2[] are examined and seen to be lists of functions. It is assumed these are lists of independent functions. In (surprising) contrast to funcs2[], the argument x in funcs3[x] changes the analysis to decide it's a vector-valued function: the two components are colored the same because they come from the same function. If evaluated before symbolic analysis (with Evaluate), the form Plot sees is {Cos[x], Sin[x]}, which looks the same as the first example and is treated the same.

$\endgroup$

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.