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.

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?

share|improve this question
    
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. –  Szabolcs Mar 6 '13 at 1:16
    
How about: With[{lims = Sequence[0, 100]}, NDSolve[...,..., {x, ##}] &@lims; Plot[..., {x, ##}] &@lims ] –  rm -rf Mar 6 '13 at 1:26
    
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? –  whuber Mar 6 '13 at 18:01
    
@Szabolcs Can you think of better tags for this question than syntax? –  Mr.Wizard Mar 9 '13 at 0:41
    
@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? –  Szabolcs Mar 9 '13 at 1:20

3 Answers 3

up vote 9 down vote accepted

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
share|improve this answer
    
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? –  Santi Aug 19 at 9:23
    
This is because the function myFunc is a 2D interpolation function, which extrapolates to zero outside specific ranges of x which depend on y. –  Santi Aug 19 at 9:27
    
@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? –  Mr.Wizard Aug 19 at 9:28
    
@Wizard ok thanks, the question is there with a small example. –  Santi Aug 19 at 9:43

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}]
share|improve this answer

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.

share|improve this answer

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.