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