Re: Protect a variable against being used as an iterator (related to the HoldAll - Evaluate problem)
- To: mathgroup at smc.vnet.net
- Subject: [mg116131] Re: Protect a variable against being used as an iterator (related to the HoldAll - Evaluate problem)
- From: Albert Retey <awnl at gmx-topmail.de>
- Date: Thu, 3 Feb 2011 05:28:37 -0500 (EST)
Am 02.02.2011 12:13, schrieb Guido Walter Pettinari:
> Dear Mathematica group,
>
> I would like to ask you a simple question that, if answered, would
> make my life much easier :-)
>
> Does anybody know how to trigger a warning/error message whenever a
> particular symbol is used as an iterator? By iterator, I mean the
> second argument of functions like Plot, Table, Sum, i.e. the "i" in
> Table [ i^2, {i, 10} ]
>
> I am looking for this feature since I get errors/unmeaning results
> whenever I use as an iterator a variable already defined in some other
> part of the code (which I may have forgot of).
> E.g., this happens with NDSolve. Take the following example:
>
> tmin = 0;
> tmax = 1;
> sol[a_] := NDSolve [ {y'[t] == a y[t], y[0] == 1}, y, {t, tmin,
> tmax} ]
> exp[a_, t_] := y[t] /. sol[a]
>
> The following Plot command does not work:
> Plot[exp[2, t], {t, tmin, tmax}]
> while changing the iterator name works:
> Plot[exp[2, x], {x, tmin, tmax}]
>
> I know that (i) the first Plot command does not work because Plot
> (like Table and Sum) has the HoldAll attribute, and (ii) using the
> Evaluate function on exp[2, t] solves the problem.
>
> However, say that I publish a package that uses a variable in the same
> way I use "t" in the above example. How does the user of the package
> know that she should not use that variable to iterate? It would be
> nice if she gets a warning message whenever she tries to do so.
>
> I guess that a workaround would be to use a Unique[] symbol, either as
> an iterator or as, say, the NDSolve independent variable.... do you
> think this is doable?
I'm not sure whether I oversee a complication in your question, but I
think proper localization of the variables used in your functions would
be the cleanest way to solve this: it wouldn't ever be necessary to warn
the user to not use a particular symbol. This is just one way to avoid
the problem altogether:
tmin = 0;
tmax = 1;
ClearAll[sol];
sol[a_, tt_] := Block[{y, t},
y[tt] /.
First[NDSolve[{y'[t] == a y[t], y[0] == 1}, y, {t, tmin, tmax}]]
]
Plot[sol[2, t], {t, tmin, tmax}]
But I think an even better approach would be to just return a function
(or InterpolatingFunction) with no argument and to not redo the NDSolve
for every of the t you want to plot, like so:
tmin = 0;
tmax = 1;
sol[a_] := sol[a] = Module[{y,t},
y /. First[NDSolve[{y'[t] == a y[t], y[0] == 1}, y, {t, tmin, tmax}]]
]
you could make a plot then like this:
Plot[sol[2][t], {t, tmin, tmax}]
but you could also do stuff like this:
sol4 = sol[4];
Plot[sol4[t],{t,tmin,tmax}]
Integrate[sol4[t],{t,tmin,tmax}]
note that that will all work with only one call to NDSolve...
hth,
albert