If you have a list, e.g.
{1, 2, 3}
then you can extract the $k$th part using Part
(list[[k]]
):
In[1]:= {1, 2, 3}[[2]]
Out[1]= 2
The problem is that if you provide a symbolic expression in the place of the list, Part
will try to decompose it:
In[1]:= list[[2]]
Part::partd: Part specification list[[2]] is longer than depth of object.
Out[1]= list[[2]]
That is, the issue occurs when the overall expression is evaluated before the value of list
is known. For example:
In[1]:= list[[2]] /. list -> {1, 2, 3}
Part::partd: Part specification list[[2]] is longer than depth of object.
Out[1]= 2
Although the final output is correct, this produces an annoying spurious error message.
It's even worse if list
is a compound expression, because then Part
will decompose it, unexpectedly changing its value. For example,
In[1]:= SinCos[x][[1]] /. SinCos -> (θ \[Function] {Sin@θ, Cos@θ})
Out[1]= x
Example
I commonly run into this when plotting one dimension of nested functions and data structures.
Suppose I have a function that generates a list of functions according to some parameters:
functions[x_Real, a_, b_, c_] := {Sin@x, Cos@x, Sin[a*x], Cos[b*x], Sin[c*x]};
Now I want to plot the first, third, and fourth functions in the list of functions with parameters $1,2,3$; in this case, $y = \sin(x), \sin(1 \cdot x), \cos(2 \cdot x)$. The obvious way is:
Plot[functions[x, 1, 2, 3][[#]]& /@ {1,3,4} // Evaluate, {x, 0, 5}]
(The Evaluate
is needed to get Plot
to treat the values as separate functions, so that they will be styled differently.) And Mathematica will dutifully plot... $y = x, 2, 3$:
{Plot[functions[x,1,2,3][[#]]&/@{1,3,4}//Unevaluated,{x,0,5}],
Plot[functions[x,1,2,3][[#]]&/@{1,3,4}//Evaluate,{x,0,5}]}
Question
How do I prevent Part[]
from trying to decompose symbolic expressions when it is evaluated?
I have a workaround below, but I'm interested in whether there's a better way to do it. Is there a standard built-in function that does what I'm looking for?
Comments
Post a Comment