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 wanted to draw some contours. I succeeded with this:

W1 = {p, -2, 2, 0.5};
W2 = {p, -10, 10, 1};
P = W1; ContourPlot[ 
 Evaluate[Union[Table[y^2 == 2 p*x, Evaluate[P]], 
   Table[x^2 == 2 p*y, Evaluate[P]]]], {x, -5, 5}, {y, -5, 5}]
P = W2;
ContourPlot[Evaluate[
  Union[Table[y^2 == 2 p*x, Evaluate[ P]], 
   Table[x^2 == 2 p*y, Evaluate[P]]]], {x, -5, 5}, {y, -5, 5}]

I don't like this solution. I used Evaluate[] a few times and I feel like it is unnecessary although without the function I get errors. Could anyone explain me that. I find the reference unhelpful (maybe that's my lack of language?) "causes expr to be evaluated even if it appears as the argument of a function whose attributes specify that it should be held unevaluated.".

share|improve this question
1  
ContourPlot[] and Table[] both have the HoldAll attribute, so the Evaluate[] is needed. –  J. M. Jun 16 '12 at 17:49
2  
See also the discussions on MathGroup with follow-ups here. Incidentally, one of the critical voices there, AES, has recently passed away. –  Jens Jun 16 '12 at 18:30
    
@jens Thanks for the pointer, I love this part: Would you really want to argue that high school students, or freshman students in college, should have to first go through a tutorial in Hold and Evaluate (and maybe also HoldAll, HoldFirst, NHoldAll, HoldAllComplete, HoldRest, SequenceHold, Extract,and Unevaluated) before they could start plotting Lists using Plot? –  belisarius Jun 16 '12 at 23:20
    
Related: mathematica.stackexchange.com/q/1375/121 –  Mr.Wizard Aug 30 '12 at 18:30
add comment

2 Answers

up vote 11 down vote accepted

ContourPlot has the attribute HoldAll. That means that it receives its arguments before they are evaluated. So, if you put as a first argument, something that evaluates to a list but it's not a list, it won't fit with the overloaded version of ContourPlot that expects a list. The same happens with the second argument of Table. Whether they end up not evaluating, using another overload, giving a warning, or simply taking more time than they should, that depends on the particular case at hand

Evaluate is something that makes the containing function behave temporarily as non-holding. Try

SetAttributes[f, HoldAll];
f[x_]:=Hold[x];
f[2+2]
f[Evaluate[2+2]]

If you don't find this neat, what's usually done is use With

With[{P = P},
 With[{lists = Union[Table[y^2 == 2 p*x, P], Table[x^2 == 2 p*y, P]]},
   ContourPlot[lists, {x, -5, 5}, {y, -5, 5}]
  ]
 ]
share|improve this answer
add comment

You needed Evaluate because you want evaluation of an argument that is normally held, both in the case of ContourPlot and Table. There are several ways to force this evaluation.

  1. Evaluate causes evaluation of an argument before the function reads it, or even "sees" it for pattern matching. It only works at the first level of the function, meaning it must wrap (be the head of) an argument, and not a sub-expression. Compare: Hold[Evaluate[2 + 2], 3 + 3] and Hold[5 + Evaluate[2 + 2]]. (Hold is used as a representative of an arbitrary function with the HoldAll attribute.)

  2. Some functions such as Plot (and FindRoot) can use the option Evaluated -> True -- for these this is superior to other methods because the range variable is still correctly localized.

  3. You can use a function which does not have a Hold attribute to cause intermediate evaluation. The most direct way is a "pure function" using &:
    Hold[1 + 2 + #] &[2 + 2]
    This works because the & function evaluates its argument before Hold ever sees it, and # (Slot) can appear anywhere in the body of the function, not merely the first level.

  4. As Rojo stated you can use With to do a lexical replacement of specific variables: With[{x = 2 + 2}, Hold[x, 3 + 3]]

  5. More complicated evaluations and insertion may be achieved using the methods I described here.

Example using the pure function method:

W1 = {p, -2, 2, 0.5};
P = W1;

ContourPlot[#, {x, -5, 5}, {y, -5, 5}] &[
  Union[Table[y^2 == 2 p*x, #], Table[x^2 == 2 p*y, #]] & @ P
]

Mathematica graphics

share|improve this answer
    
@Rojo actually I didn't try Evaluated -> True in this case before posting; I am surprised to find that it doesn't work here. Oops! –  Mr.Wizard Jun 16 '12 at 19:57
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.