This question started me thinking about how Mathematica detects multiple functions being plotted. I find that I really do not understand the process.
Consider:
Plot[{1, Sequence[2, 3], 4}, {x, 0, 1}, PlotRange -> {0, 5}]
I can understand that Plot
finds three elements in the list initially, but how does it "know" to style 2
and 3
the same? It is as though there is a memory of what part of the starting list those two elements came from. How does this work?
Well, it knows that there three arguments just so:
In[13]:= Function[x, Length[Unevaluated[x]], HoldAll][{1,
Sequence[2, 3], 4}]
Out[13]= 3
If x is allowed to evaluate, then
In[14]:= Function[x, Length[x], HoldAll][{1, Sequence[2, 3], 4}]
Out[14]= 4
EDIT: One sees it better with:
In[15]:= Hold[{1, Sequence[2, 3], 4}]
Out[15]= Hold[{1, Sequence[2, 3], 4}]
in other words, flattening of Sequence requires evaluator.
EDIT 2: I clearly missed the real question posed and will try to answer it now.
Once Plot determines the number of argument it builds {{ style1, Line ..}, {style2, Line..}, ... }. In the case of {1,Sequence[2,3],4} we get the following structure:
In[23]:= Cases[
Plot[{1, Sequence[2, 3], 4}, {x, 0, 1},
PlotRange -> {0, 5}], {_Hue, __Line},
Infinity] /. {x_Line :> Line, _Hue -> Hue}
Out[23]= {{Hue, Line}, {Hue, Line, Line}, {Hue, Line}}
When plotting {1,{2,3},4} we get a different structure:
In[24]:= Cases[
Plot[{1, List[2, 3], 4}, {x, 0, 1},
PlotRange -> {0, 5}], {_Hue, __Line},
Infinity] /. {x_Line :> Line, _Hue -> Hue}
Out[24]= {{Hue, Line}, {Hue, Line}, {Hue, Line}, {Hue, Line}}
because lists would be flattened, just not using the evaluator. So as you see the tagging in the same color occurs because Sequence[2,3] is treated as a black-box function which returns a list of two elements:
In[25]:= g[x_?NumberQ] := {2, 3}
In[26]:= Cases[
Plot[{1, g[x], 4}, {x, 0, 1}, PlotRange -> {0, 5}], {_Hue, __Line},
Infinity] /. {x_Line :> Line, _Hue -> Hue}
Out[26]= {{Hue, Line}, {Hue, Line, Line}, {Hue, Line}}
I was trying to build a top-level implementation which would build such a structure, but one has to fight the evaluator. For example:
In[28]:= Thread /@ Function[x,
Thread[{Hold @@ {Range[Length[Unevaluated[x]]]}, Hold[x]}, Hold]
, HoldAll][{1, Sequence[2, 3], 4}]
Out[28]= Hold[Thread[{{1, 2, 3}, {1, Sequence[2, 3], 4}}]]
Now we have to evaluate the Thread without evaluating its arguments, which would give {{1, 1}, {2, Sequence[2,3]}, {3, 4}}, where the first element of the list is a tag, and the subsequent once are functions to be sampled.
Hope this helps.
It's not that difficult to imagine a process which results in this output. I don't have additional proof that this is indeed what happens, but it is reasonable to assume that Plot
loops through the list of functions that were passed to it, and associates a style with each. Then it proceeds to evaluate each of them after setting a value to the plot variable. Normally each "function" (element in the list passed to Plot
) would return a real number. However, since version 6, Mathematica can handle those that return lists of numbers too, with the flaw that it uses the same styling for the complete list. Version 5 would throw an error for functions that returned lists.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With