Group Abstract Group Abstract

Message Boards Message Boards

Why does Part[list, n] work in one place, but not work consequently?

GROUPS:
As a new Mathematica user I am puzzled by the following, where the Part[list, n] function - or more accurately list[] - doesn't seem to have consequent results. For example, in MM 9 on Windows 7 if I say:
f[x_, y_] := (x + y)^2
curves = Expand[Thread[f[{1, 2, 3}, {x, y, z}]]]
bounds = {{x, -10, 10}, {y, -10, 10}, {z, -10, 10}}

Plot[curves[[1]], {x, -10, 10}]
this works, but Plot[curves[[1]], bounds[[1]]] returns an error even though bounds[[1]] returns {x,-10,10}. Anbody know why this is?
POSTED BY: Grant Hearn
Answer
9 months ago
That is because Plot is HoldAll, however one can do
Plot[curves[[1]], Evaluate[bounds[[1]]]]
POSTED BY: Ilian Gachevski
Answer
9 months ago
OK - I get it, that solves it. Thanks very much!
POSTED BY: Grant Hearn
Answer
9 months ago
This is an order of operations issue - you need to make sure that the second argument to Plot (bounds[[1]]) is evaluated at the appropriate time. One way of doing this is to use the Evaluate function:

http://reference.wolfram.com/mathematica/ref/Evaluate.html

For example, this should work:
Plot[curves[[1]], Evaluate@bounds[[1]]]

Note that the reason for this special behavior is that the Plot function has the attribute HoldAll:
Attributes[Plot]
which means that the arguments to Plot are maintained in an unevaluated form.

EDIT: Oh well, Ilian already answered this.
POSTED BY: Karl Isensee
Answer
9 months ago
OK - why does HoldAll only affect the second argument to Plot[ ] and not the first?
POSTED BY: Grant Hearn
Answer
9 months ago
HoldAll does affect all arguments. The evaluator passes the first argument to Plot unevaluated, which is then free to use it in any way, including evaluation at each sample point.
POSTED BY: Ilian Gachevski
Answer
9 months ago
That makes sense, but in what way is the simple list {x, -10, 10} passed to Plot[ ] when the list is provided as a literal instead of the result of a function call? If both are unevaluated, wha'ts the difference between the literal and the result of bounds[[1]]? Sorry about all the questions, but I'd lke to get a proper handle on how MM does things..
POSTED BY: Grant Hearn
Answer
9 months ago
 
Plot needs a valid plot range specification, which {x, -10, 10} is, but bounds[[1]] --- in its unevaluated form --- is not.
POSTED BY: Ilian Gachevski
Answer
9 months ago
Sorry Ilian, I think I'm expressing myself badly. Why does Plot[ ] evaluate the result of curves[[1]] and not of bounds[[1]]?
POSTED BY: Grant Hearn
Answer
9 months ago
I looked up HoldAll in the documentation, where it's defined as: an attribute which specifies that all arguments to a function are to be maintained in an unevaluated form. Simple enough, but that doesn't explain why Plot[ ] then evaluates curves[[1]] but not bounds[[1]].
POSTED BY: Grant Hearn
Answer
9 months ago
I tried Head[[curves[[1]]] -> Plus; Head[[bounds[[1]]] -> List: is that why?
POSTED BY: Grant Hearn
Answer
9 months ago
It might be more clear to you what is happening if you wrapped FullForm around the results:
FullForm[curves[[1]]]
FullForm[bounds[[1]]]
bounds[[1]] has curly braces around it, indicating it is a list.  curves[[1]] is just 3 terms added together, so it will have the head Plus (indicating addition).
POSTED BY: Karl Isensee
Answer
9 months ago
Thanks Karl - my problem is not with the head of the arguments, it's with the logic being followed. If HoldAll applies to ALL arguments, why is curves[[1]] evaluated by Plot[ ] and not bounds[[1]]? That's what seems illogical to me. I though that Plus might be something that needed less(?) evaluation than List and that's what's causing the problem? Does the list have to be flattend first before being evaluated and this is what's causing the 'problem'?
POSTED BY: Grant Hearn
Answer
9 months ago
Perhaps I should have emphasized this -- HoldAll only controls what happens with the arguments before Plot is called. What may take place inside of Plot is a different story, but does not contradict the HoldAll documentation in any way.

There can be, of course, further questions about the design and implementation, for example why does Plot need to be HoldAll. Other people are better qualified to answer that, but I believe it makes some of the advanced visualization machinery much easier to implement.
POSTED BY: Ilian Gachevski
Answer
9 months ago
In other words: it is like it is. LOL! Thanks for the time and trouble guys.
POSTED BY: Grant Hearn
Answer
9 months ago
The first argument has Hold because of this:
x = 2
Plot[x + x^2, {x, 0, 2}]
If it was first evaluated, it would just say Plot[6,{x,0,2}]  which would be constant.

Also read: http://library.wolfram.com/conferences/devconf99/villegas/UnevaluatedExpressions/ (a long read but maybe worth it).

The problem is very complicated as there are many similar/related commands: Defer, Unevaluated, Hold, HoldForm, HoldComplete, HoldAllComplete, HoldPattern, SequenceHold...
POSTED BY: Sander Huisman
Answer
9 months ago
To produce any plot, clearly the function to be plotted needs to be evaluated numerically at the different sampling points. This is why something like Plot[curves[[1]], {x, -10, 10}] works, but note it needs to perform the part taking operation repeatedly for each numerical value of x. It hardly impacts this example, but there are cases where it is more efficient to wrap Evaluate around the first argument.

Another place where evaluation semantics are relevant is the difference between the following two plots
Plot[Table[x^k, {k, 2, 3}], {x, 4, 5}]

Plot[Evaluate[Table[x^k, {k, 2, 3}]], {x, 4, 5}]
In the second one, the curves are colored differently because the symbolic evaluation allows Plot to see it has been given a list.
POSTED BY: Ilian Gachevski
Answer
9 months ago
With is used to inject a value into an expression, then releases it. Handy for building up arguments inside HoldAll functions like Plot.
plotCurves[n_] := With[{b = bounds[[n]]}, Plot[curves[[n]], b]]
This version inserts both values, similar to Plot[Evaulate@curves[[1]], Evaluate@bounds[[1]] ]
plotCurves[n_] := With[{c = curves[[n]], b = bounds[[n]]}, Plot[c, b]]
plotCurves /@ Range[3]
POSTED BY: Christopher French
Answer
9 months ago