5
$\begingroup$

Let's say I want to take this plot:

r = 3;
DensityPlot[x^2 + y^2, {x, -r, r}, {y, -r, r}]

and make the x and y limits be returned from some function (maybe because I am making a bunch of plots, and I want to be concise). I assumed that the following would work:

Lim[r_] := Sequence[{x, -r, r}, {y, -r, r}]
ContourPlot[x^2 + y^2, Lim[3]]

But it doesn't; instead I get: ContourPlot called with 2 arguments; 3 arguments are expected.. From this message and from the stack trace, it is clear that ContourPlot (and presumably other plot types) checks the number of arguments before it evaluates any of the arguments, unless the head is a Sequence. If we just take a sequence object and pass it directly to the plot, it works fine:

r = 3;
DensityPlot[x^2 + y^2, Sequence[{x, -r, r}, {y, -r, r}]]

So it looks like the order of evaluation prevents the use of functions that return sequences in this manner (since in general, the number of arguments will likely be altered by the inclusion of a sequence).

I can think of a bunch of other ways to accomplish this task, but this seems to me to be the simplest; is there any reasonable way of making this work?

$\endgroup$
4
  • 1
    $\begingroup$ You could use ContourPlot[x^2 + y^2, Evaluate@Lim[3]]. $\endgroup$ Commented Jan 3 at 16:15
  • 1
    $\begingroup$ Or ContourPlot[x^2 + y^2, ##] &@Lim[3] $\endgroup$ Commented Jan 3 at 16:38
  • 2
    $\begingroup$ Or ContourPlot @@ {x^2 + y^2, Lim[3]} $\endgroup$ Commented Jan 3 at 17:24
  • 1
    $\begingroup$ Or ContourPlot[x^2 + y^2, Evaluate@Lim[3]]. $\endgroup$ Commented Jan 3 at 17:58

1 Answer 1

7
$\begingroup$

One of the programmed advantages of the *Plot functions is the localization of the domain variables, x and y in this case. Do you wish localization to be preserved? If not, the first two comments under the OP or this, which is what I often do:

lim[r_] := Sequence[{x, -r, r}, {y, -r, r}]
ContourPlot @@ {x^2 + y^2, lim[3]}

If I want to localize x and y for the plot, I would use Block above, as it is used in the alternative below:

xdom = {-3, 3};
ydom = {-3, 3};
Block[{x, y},
 ContourPlot @@ {x^2 + y^2, Flatten@{x, xdom}, Flatten@{y, ydom}}
 ]

Here's a use-case I encounter frequently:

yIFN = NDSolveValue[{y''[x] == Exp[y[x]], y[0] == 0, y'[0] == 0}, 
   y, {x, 0, 10}];
Block[{t},
 Plot @@ {yIFN[t], Flatten@{t, yIFN["Domain"]}}
 ]

Since the domain from solving the ODE is not guaranteed to be 0 <= x <= 10, I extract the domain from the interpolating function.

Another way, using Hold[] + injector:

lim[r_] := Hold[{x, -r, r}, {y, -r, r}]
x = 7; y = 12; (* to prove localization *)
lim[3] /. Hold[xx_, yy_] :> ContourPlot[x^2 + y^2, xx, yy]

Injector references:

$\endgroup$
0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.