10
$\begingroup$

Plot[2*x^2 - x + 2, {x, -1, 1}] plots a function of x from -1 to 1. As far as I can see, I cannot "save" this range in a variable:

u = {x, -1, 1};
Plot[2*x^2 - x + 2, u]

Generates Plot::pllim: Range specification u is not of the form {x, xmin, xmax}. Hopefully my intention is obvious, what is the most concise way of accomplishing it?

Because someone will wonder why I could possibly want to do this: I have

NDSolve[..., ..., {t, 0, 100}];
Plot[..., {t, 0, 100}];

I don't want to need to modify both 100's as my desired range changes. Yes, I could use variables t0 and t1, but is what type is the range/domain expression? Why can't I store it directly?

$\endgroup$
6
  • $\begingroup$ The reason why what you tried did not work is that Plot has the HoldAll attribute (this is to make it work even if x has a value). Unfortunately I see no convenient way to get around this. As MrW pointed it out, Plot[..., Evaluate[u]] is not robust: it won't work if x has a value. Yes, this is annoying, and I'd also like a really convenient way to store these ranges. $\endgroup$
    – Szabolcs
    Mar 6, 2013 at 1:16
  • $\begingroup$ How about: With[{lims = Sequence[0, 100]}, NDSolve[...,..., {x, ##}] &@lims; Plot[..., {x, ##}] &@lims ] $\endgroup$
    – rm -rf
    Mar 6, 2013 at 1:26
  • $\begingroup$ Maybe I'm missing something, but it seems the key point is to save the limits $-1$ and $1$ in the variable u and that it wouldn't do any harm to re-specify the variable x explicitly in Plot. So why not u={-1,1}; Plot[f[x], Evaluate@Prepend[u,x]]? Or is it important that x be referenced within u itself? If so, why? $\endgroup$
    – whuber
    Mar 6, 2013 at 18:01
  • $\begingroup$ @Szabolcs Can you think of better tags for this question than syntax? $\endgroup$
    – Mr.Wizard
    Mar 9, 2013 at 0:41
  • $\begingroup$ @Mr.Wizard I tried, please review. I think this is also related to "macro expansion". There were questions about that, but I can't find them now. Maybe they were on SO. This is really about convenience, making it easier to type code. Maybe we should have a tag for things like that? $\endgroup$
    – Szabolcs
    Mar 9, 2013 at 1:20

3 Answers 3

11
$\begingroup$

Better methods

My original answer was pretty poor and I'll show you why.

Suppose x has a value assigned: x = 7. This does not bother Plot:

Plot[2*x^2 - x + 2, {x, -1, 1}]  (* outputs graphic *)

It however will prevent my earlier suggestions from working:

Plot[2*x^2 - x + 2, Evaluate@u]

During evaluation of In[23]:= Plot::itraw: Raw object 7 cannot be used as an iterator. >>

Plot[2 x^2 - x + 2, {7, -1, 1}]

Instead you should store your range in a way that holds the plot parameter unevaluated:

u = Hold[{x, -1, 1}];

Then you need a way to put this inside the Plot expression without it evaluating. This can be done with a Function and a hold attribute and Apply:

Function[spec, Plot[2*x^2 - x + 2, spec], HoldAll] @@ u  (* outputs graphic *)

Or more tersely with the "injector pattern":

u /. _[spec_] :> Plot[2*x^2 - x + 2, spec]  (* outputs graphic *)

Old answer

You just need Evaluate:

u = {x, -1, 1};

Plot[2*x^2 - x + 2, Evaluate @ u]

Mathematica graphics

Or as I often prefer, Function:

Plot[2*x^2 - x + 2, #] & @ u
$\endgroup$
4
  • $\begingroup$ Hi @Mr.Wizard, I have a problem that could be related but doesn't seem to work for me. I would like the range limits to depend on some other function or list, something like: Plot[Evaluate@Map[myFunc[x, #], {x, 0, rangeFunc[yValues]}&, yValues]] where rangeFunc gives me a number for each y. Is it possible? $\endgroup$
    – Santiago
    Aug 19, 2014 at 9:23
  • $\begingroup$ This is because the function myFunc is a 2D interpolation function, which extrapolates to zero outside specific ranges of x which depend on y. $\endgroup$
    – Santiago
    Aug 19, 2014 at 9:27
  • $\begingroup$ @Santi I have trouble understanding what you want. Would you please post a new question with examples of both the input and output that you want? $\endgroup$
    – Mr.Wizard
    Aug 19, 2014 at 9:28
  • $\begingroup$ @Wizard ok thanks, the question is there with a small example. $\endgroup$
    – Santiago
    Aug 19, 2014 at 9:43
5
$\begingroup$

To take a more advanced approach in response to Szabolcs's comment, one can use UpValues. I define a new kind of set function as follows:

SetAttributes[setSpec, HoldAllComplete]

setSpec[s_Symbol, spec__] := s /: h_[pre__, s, post___] := h[pre, spec, post]

Then make an assignment, and use it:

setSpec[u, {x, 0, 10}];

Plot[Sin[x], u, PlotStyle -> Red]

Mathematica graphics

Or with more than one specification:

setSpec[v, {x, -3, 3}, {y, -3, 3}, StreamStyle -> "Pointer"]

StreamPlot[{-1 - x^2 + y, 1 + x - y^2}, v,
 PlotLabel -> s, 
 StreamScale -> {Full, All, 0.03}]
$\endgroup$
5
$\begingroup$

I have a simple mind and like simple methods. In this case, I suggest using a formal parameter.

u = {\[FormalX], -1, 1};

The character \[FormalX] can be typed using the keystrokes [esc]$x]esc].

Using \[FormalX] rather than x is robust because \[FormalX] has the Protected attribute and can not be bound to a value.

\[FormalX] = 42; ValueQ@\[FormalX]

Set::wrsym: Symbol \[FormalX] is Protected.

False

With u defined as above, you can make your plot by evaluating

Plot[2*\[FormalX]^2 - \[FormalX] + 2, Evaluate@u]

or by evaluating

With[{u = u}, Plot[2*\[FormalX]^2 - \[FormalX] + 2, u]]

Should you dislike the extra typing needed to insert \[FormalX] or should you want the freedom to use a parameter name entirely of your own choosing, you can roll your own formal parameters.

SetAttributes[makeFormal, HoldFirst];
makeFormal[u_Symbol] := (Clear[u]; Protect[u];)

Unprotect@x;
x = 42;
makeFormal@x;
Print[Attributes[x]];
ValueQ@x

{Protected}

False

Now x will act just like \[FormalX].

u = {x, -1, 1};
Plot[2*x^2 - x + 2, Evaluate@u]

The above is now safe because x can no longer take a value.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.