I want to describe an issue I have been having with Plot using With to keep defined parameters 'local'. I am not necessarily asking for a fix: the problem I have is one of understanding.
Sometimes I use a construction such as the following to obtain a Plot:
Method 1
plot1 = With[{vmax = 10, km = 10},
Plot[Evaluate#((vmax x)/(km + x)), {x, 0, 100},
AxesOrigin -> {0, 0}]]
I like this method, and it is reasonably clear even to non-Mathematica users exactly what is going on.
When the equations to be plotted become more complex, I like to define them external to the plot (using SetDelayed). For example:
f[x_] := (vmax x)/(km + x)
However, the following does not work
Method 2
plot2 = With[{vmax = 10, km = 10},
Plot[Evaluate#f[x], {x, 0, 100}, AxesOrigin -> {0, 0}]]
I have always naively thought that it should. However, based on the Help statement that
Plot treats the variable x as local,
effectively using Block
I have used various workarounds, mostly something like the following
Method 3
plot3 = Plot[With[{vmax = 10, km = 10}, Evaluate#f[x]], {x, 0, 100},
AxesOrigin -> {0, 0}]
This one seems very awkward, and usually requires further explanation even to Mathematica users.
Plot outputs
However, recently I found out by chance that substituting Block for With in Method 2 works exactly as expected.
I can, for example, do something like the following (which to me seems a very versatile approach):
plot4 = Block[{vmax = {10, 10, 10}, km = { 10, 100, 1000}},
Plot[Evaluate#f[x], {x, 0, 100}, AxesOrigin -> {0, 0},
PlotStyle -> {Red, Green, Blue}]]
giving
My questiions are as follows. What is the explanation for the difference in behaviour with With in Method 1 and 2? Should I have expected Method 2 not to work? Furthermore, what is the explanation for the difference in behaviour with Block and With in Method 2? Should I have been able to predict that Block would work?
Funnily enough many workarounds have been suggested to me by those more experienced than I, but nobody suggested using Block.
Finally, I need to keep vmax and km local.(They have been defined algebraically elsewhere)
Your question is not so much about Plot as it is about how the scoping constructs work. The main confusion here is due to the differences between lexical and dynamic scoping. And the main culprit is this definition:
f[x_] := (vmax x)/(km + x)
The problem with it is that it makes f implicitly depend on the global symbols (variables) vmax and km. I am very much against this sort of constructs since they lead to infinite confusion. Now, what happens can be illustrated with the following example:
In[55]:= With[{vmax =1, km = 2},f[x]]
Out[55]= (vmax x)/(km+x)
To understand why this happens, one must understand what the lexical scoping means. We know that With has a HoldAll attribute. The way it works is that it looks are what is literally inside it, and substitutes variables found literally in the body with their values from the declaration list. This happens during the variable-binding stage, and only then it lets the body to evaluate. From this, it is clear that the following will work:
In[56]:= With[{vmax =1, km = 2},Evaluate[f[x]]]
Out[56]= x/(2+x)
This worked because Evaluate overrides the "part" of HoldAll attribute of With, forcing the body to evaluate before anything else (variable binding, and subsequent body evaluation). Therefore, it would be completely equivalent to use just With[{vmax = 1, km = 2}, (vmax x)/(km + x)] above, as you can see with Trace. The next part of the puzzle is why
With[{vmax = 10, km = 10}, Plot[Evaluate#f[x], {x, 0, 100}, AxesOrigin -> {0, 0}]]
does not work. This is because this time we do not evaluate the body first. The presence of Evaluate affects only f[x] inside Plot, but not the evaluation of Plot itself inside With. This is illustrated by
In[59]:= With[{vmax = 10, km = 10}, q[Evaluate#f[x]]]
Out[59]= q[(vmax x)/(km + x)]
Moreover, we do not want Plot to evaluate first, since then the values of vmax and km will not be defined. However, all that With sees is f[x], and since the parameters vmax and km are not literally present in there (lexical scoping, remember), no substitution will be made. Should we use Block here, and things will work, because Block uses dynamic scoping, meaning that it redefines values in time (part of the execution stack if you wish), rather than in place. Therefore, using Block[{a =1, b =2}, ff[x]] where ff implicitly depends on a and b is (roughly) equivalent to a=1;b=2;ff[x] (with the difference that a and b resume their global values after the Block scope is left). So,
In[60]:= Block[{vmax = 10, km = 10}, q[Evaluate#f[x]]]
Out[60]= q[(10 x)/(10 + x)]
To make the With version work, you'd have to inject the expression for f[x] (r.h.s), for example like so:
In[63]:= Unevaluated[With[{vmax = 10, km = 10}, q[f[x]]]] /. DownValues[f]
Out[63]= q[(10 x)/(10 + x)]
Note that this won't work:
In[62]:= With[{fx = f[x]}, With[{vmax = 10, km = 10}, q[fx]]]
Out[62]= q[(vmax x)/(km + x)]
But the reason here is quite subtle: while outer With evaluates before the inner one, it spots the variable name conflicts and renames its variables. Rules are much more disruptive, they don't respect inner scoping constructs.
EDIT
If one insists on nested With-s, here is how one can fool the name conflict resolution mechanism of With and make it work:
In[69]:= With[{fx = f[x]}, With ## Hold[{vmax = 10, km = 10}, q[fx]]]
Out[69]= q[(10 x)/(10 + x)]
Since outer With can no longer detect the presence of inner With (using Apply[With,Hold[...]] makes the inner With effectively dynamically generated), it does not make any renamings, and then it works. This is a general trick to fool lexical scoping name resolution mechanism when you don't want renaming, although the necessity to use it usually indicates a bad design.
END EDIT
But I digressed. To summarize, making your second method work is quite hard and requires really weird constructs like
Unevaluated[ With[{vmax = 10, km = 10}, Plot[Evaluate#f[x], {x, 0, 100},
AxesOrigin -> {0, 0}]]] /. DownValues[f]
or
With[{fx = f[x]},
With ## Hold[{vmax = 10, km = 10},
Plot[Evaluate#fx, {x, 0, 100}, AxesOrigin -> {0, 0}]]]
Once again: all this is because With must "see" the variables explicitly in the code, to make replacements. In contrast, Block does not need that, it replaces values dynamically at the moment of evaluation, based on their modified global values, as if you made assignments, this is why it works.
Now, the real culprit is your definition of f. You could have avoided all these troubles should you have defined your f with explicit parameter-passing:
ff[x_, vmax_, km_] := (vmax x)/(km + x)
Now, this works out of the box:
With[{vmax = 10, km = 10},
Plot[Evaluate#ff[x, vmax, km], {x, 0, 100}, AxesOrigin -> {0, 0}]]
because the parameters are explicitly present in the function call signature, and so are visible to With.
To summarize: what you observed is a consequence of the interplay between lexical and dynamic scoping. Lexical scoping constructs must "see" their variables explicitly in the code at the variable-binding stage (before evaluation), or they won't be effective. Dynamic scoping effectively modifies values of symbols, and is in this sense less demanding (the price you pay is that the code using lots of dynamic scoping is harder to understand, since it mixes state and behavior). The main reason for trouble is the function definition that makes implicit dependencies on global symbols (that are not in the formal parameter list of the function). It is best to avoid such constructs. It is still possible to make things work, but this is considerably more complicated (as was demonstrated above), and, at least for the case at hand, for no good reason.
Just two comments:
using Block, you don't need to use Evaluate. That is, Block[{vmax = 10, km = 2}, Plot[f[x], {x, 0, 100}] will work.
Another way to do this is to define substitution rules:
rule = {vmax -> 10, km -> 10}; Plot[f[x] /. rule, {x, 0, 100}]
The advantage is that you can re-use the rule in other statements.
In addition, you can define multiple substition rules for different cases: rule1 = {vmax -> 10, km -> 10}, rule2 = {vmax -> 2, km -> 2}
Related
I like to use With[] with constants that I need to use in 2 different places.
Instead of typing the same long list of constants in 2 places, I have been trying to figure how to use a variable for this list, and then use this variable in the few places I want to use the list.
The problem is that I need to Hold the list and then ReleaseHold it later when time to use it, but I can't get this part right. (tried many things, nothing working for me)
Here is an example:
With[{$age = 2, $salary = 3},
x = $age
]
With[{$age = 2, $salary = 3},
y = $age
]
I do not want to type the same constants around (in my case, these are very long), and I was trying to do something like this:
c = HoldForm[{$age = 2, $salary = 3}]
With[Release[c],
x = $age
]
With[Release[c],
y = $age
]
I tried many other combinations of the above. So many version of Hold* and Release*, I find them all very confusing.
question is: Any one knows how to do the above, so I can reused the list in more than one place without actually copy it?
To put this in context, here is an example where this would be needed:
I can't do surround everything with With in Manipulate: (and I can't put a With outside Manipulate for what I am doing, everything must be inside Manipulate)
Manipulate[
Evaluate#With[{$age = 2, $salary = 3},
x;
$age,
{{x, $age, "age="}, 0, 10, 1}
]
]
Not valid syntax. (due to the "," needed to separate the Manipulate expression from the controls). (it now thinks With has 3 arguments)
I could ofcourse do
Manipulate[
With[{$age = 2, $salary = 3},
x;
$age
],
Evaluate#With[{$age = 2, $salary = 3},
{{x, $age, "age="}, 0, 10, 1}
]
]
But as you see, I had to copy the list of constants around.
If I can figure how to define the list once, I can put it in the Initialization section on Manipulate and use it, like this:
Manipulate[
With[ReleaseHold[myList],
x;
$age
],
Evaluate#With[ReleaseHold[myList],
{{x, $age, "age="}, 0, 10, 1}
],
Initialization :>
(
myList = HoldAll[{$age = 2, $salary = 3}];
)
]
I think what I want to do is possible, I just can't figure the correct commands to use for the Hold/Release hold part.
edit (1)
I thought I put an example of why I want to use constants in With.
I came up with this new method :) to allow me to simulate a record or a struct.
The constant values will be the named field of the record (which is just a list really).
For field name, I give it a sequential number, (I start from 1) and I use $field=number, and then in the code, I write struct[[$field]]=... to access the field.
I need to share the values of the named fields to the struct between the Manipulate expression and the control area, since both need to use the same struct.
Here is a simple example below of a Manipulate that reads the age and current salary from the UI and the expression and assigns new salary based on current salary and ago.
The record is used to communicate the data between the control area and the expression and lower level functions.
In my current demo, I have hundreds of such parameters, (I actually have now few demos, all in one demo, and I flip between different UI layouts (controls) based on which choice is selected on the UI) and using records will simplify life for me, since now I can make function calls, and just pass few parameters, records that contain the UI parameters, and not 100's of the individual parameters, which is what I have to do now. As I said many times before, Mathematica needs a real record/struct as a basic data struct, in addition to List, and Array and such, which is integrated into M.
(the UI parameters have to be send, all, to lower level functions, and there is no other choice than doing this. I do not want to use global variables. Bad design).
I also can now pass this record by reference If I want to to allow updates to happen into it inside other much lower level functions. I am still evaluating this method to see if I can actually use it in my main code.
(*verison 1.1*)
Manipulate[
With[{$age = 1, $salary = 2, $newSalary = 3},
updateRecord[record_] := Module[{},
(*update/process UI input*)
record[[$newSalary]] = record[[$salary]] + record[[$age]]*10;
(*return result*)
record
];
(*call lower level function to process UI parameters*)
myRecord = updateRecord[Unevaluated#myRecord];
(*display the result *)
Grid[{
{"age=", myRecord[[$age]]},
{"current salary=", myRecord[[$salary]]},
{"new salary=", myRecord[[$newSalary]]}
}]
],
(* build the UI controls *)
Evaluate#With[{$age = 1, $salary = 2, $newSalary = 3},
Grid[{
{"age=",
Manipulator[Dynamic[age, {age = #; myRecord[[$age]] = age} &],
{10, 100, 1}, ImageSize -> Tiny], Dynamic[age]},
{"salary=",
Manipulator[
Dynamic[salary, {salary = #; myRecord[[$salary]] = salary} &],
{10, 10000, 10}, ImageSize -> Tiny], Dynamic[salary]}
}
]
],
{{myRecord, {10, 100, 100}}, None},
{{age, 10}, None},
{{salary, 1000}, None},
TrackedSymbols -> {age, salary}
]
edit(2)
On trying to use Leonid below, I can use it in the Manipulate expression, but can't figure how to use in the control area.
Here is the original example using With in 2 places:
Manipulate[
With[{$age = 2, $salary = 3},
x + $age
],
Evaluate#With[
{$age = 2, $salary = 3},
{{x, $age, "age="}, 0, 10, 1}
],
{x, None}
]
now using the new Leonid method below, this is what I have so far:
Manipulate[
env[
x + $age
],
Evaluate#With[
{$age = 2, $salary = 3},
{{x, $age, "age="}, 0, 10, 1}
],
{x, None},
Initialization :>
(
ClearAll[makeCustomEnvironment];
SetAttributes[makeCustomEnvironment, HoldAll];
makeCustomEnvironment[values : (_Symbol = _) ..] :=
Function[code, With ## Hold[{values}, code], HoldAll];
env = makeCustomEnvironment[$age = 2, $salary = 3];
)
]
But is it possible to use it for the control also? I can't just do this:
Manipulate[
env[
x + $age
],
env[
{$age = 2, $salary = 3},
{{x, $age, "age="}, 0, 10, 1}
],
{x, None},
Initialization :>
(
ClearAll[makeCustomEnvironment];
SetAttributes[makeCustomEnvironment, HoldAll];
makeCustomEnvironment[values : (_Symbol = _) ..] :=
Function[code, With ## Hold[{values}, code], HoldAll];
env = makeCustomEnvironment[$age = 2, $salary = 3];
)
]
as the above gives many errors.
edit(3)
deleted as was incorrect
edit (4)
deleted content of edit(3) above as it included a user error on my side reporting an issue.
Here is the WRI support response to why I was getting the error
Manipulate::vsform: Manipulate argument env[{{age,100,age},10,200,1}] does
not have the correct form for a variable specification. >>
When I was writing the following code:
Manipulate[
env[
record[[$age]] = age;
record[[$salary]] = 60*age;
{record[[$age]], record[[$salary]]}
],
env[
{{age, 100, "age"}, 10, 200, 1}
],
{{record, {40, 5}}, None},
{{salary, 40000}, None},
TrackedSymbols :> {age},
Initialization :>
(
makeCustomEnvironmentAlt =
Function[Null, Function[code, With ## Hold[{##}, code], HoldAll],
HoldAll];
env = makeCustomEnvironmentAlt[$age = 1, $salary = 2];
)
]
This is the support explanation of why this error came showed up:
The issue is specifically with the section:
Evaluate#env[{{age, 100, "age"}, 10, 200, 1}]
Manipulate doesn't really evaluate until it gets to the Initialization
option, but it will check its input for correct form. Mathematica reads the
main body of the Manipulate before running the Initialization option. This
is can be verified by using a Print statement:
Initialization -> (Print["Test"];
makeCustomEnvironmentAlt =
Function[Null, Function[code, With ## Hold[{##}, code], HoldAll],
HoldAll];
env = makeCustomEnvironmentAlt[$age = 1, $salary = 2];
Print["Test"])
Test does not print.
Getting around this will be probably not be clean.
....
Having the code for the controller for age depend on evaluation of
some function which must be initialized does not appear to be possible
with simply Manipulate.
I hope this information helps. And thanks for everyone's help and also for WRI support and explanation.
What I'd do is to write a function generator to create custom (lexical) environments:
ClearAll[makeCustomEnvironment];
SetAttributes[makeCustomEnvironment, HoldAll];
makeCustomEnvironment[values : (_Symbol = _) ..] :=
Function[code, With ## Hold[{values}, code], HoldAll];
This takes a declaration list and creates a pure function which uses With internally with encapsulated constants. I used With##Hold[...] to fool the renaming mechanism of Function so that it would not rename the variables inside With (instead of With, one could use the withRules function suggested by #Szabolcs, which would lead to a slightly different substitution semantics).
Now, we create our custom function:
env = makeCustomEnvironment[$age = 2, $salary = 3];
And use it like so:
In[25]:=
env[x=$age];
x
Out[26]= 2
In[27]:=
env[y=$age];
y
Out[28]= 2
The advantage of this construct with respect to a saved variable (with rules or whatever) is that here we encapsulate behavior rather than state. This is arguably cleaner and more along the functional programming paradigm (we create here a closure rather than instantiate a class).
EDIT
Apparently, the rules for demonstrations are pretty strict, and won't allow the sugested code. This version will hopefully be ok:
makeCustomEnvironmentAlt =
Function[Null,
Function[code, With ## Hold[{##}, code], HoldAll],
HoldAll]
But you'll have to remember the format of input arguments (which was clear for the initial solution due to the use of suggestive pattern).
I would recommend using Replace and Rules instead of With for this purpose. See for example the withRules function I described here, which I use for a purpose similar to what you describe: injecting a predefined list of constants into code without having to define those constants as global variables.
ClearAll[withRules]
SetAttributes[withRules, HoldAll]
withRules[rules_, expr_] :=
Internal`InheritedBlock[
{Rule, RuleDelayed},
SetAttributes[{Rule, RuleDelayed}, HoldFirst];
Unevaluated[expr] /. rules
]
Usage:
constants = { a -> 1, b :> 2+2 }
withRules[ constants, a+b ]
Note that you can use both -> and :> so there's no need for Holding the constants.
A word of warning:
Also note that it is different from With in that it doesn't really localize variables. Consider With[{x=1}, With[{x=2}, x]], which renames the x in the inner With to avoid conflict. withRules doesn't do this: is ruthlessly replaces every x within withRules[{x-> ...}, ...] regardless of whether it appears in another Function, With or Module or not.
Regarding your Manipulate example, I would just wrap the whole Manipulate with a With, as in
With[
{age = 2},
Manipulate[{x, age}, {{x, age}, 0, 10, 1}]
]
Can you explain why you want to have everything inside the Manipulate (if you're not manipulating age), and why you can't just wrap it with the With?
When I use Manipulate I can do:
Manipulate[x, {u, 1, 10}]
In reality my controls are many and complicated, so I would prefer to take their
definition out of the Manipulate expression, like that:
control = {u, 1, 10}
Manipulate[x, control]
But that does result in a an error:
Manipulate argument control does not have the correct form for a \
variable specification.
Why doesn't it work that way?
Manipulate has the HoldAll attribute. You can force control to evaluate and everything works ok
control = {u, 1, 10};
Manipulate[x[u], Evaluate[control]]
The problem with this is that the variable u is not properly localised, so if you have already set, e.g., u=1 somewhere, then the Manipulate will return an error.
It might be better if you use appropriate scoping constructs such as With or DynamicModule depending on exactly what you're trying to do.
This is maybe overkill, but it ensures that u is local and moves control outside of the manipulate:
DynamicModule[{u}, With[{control = {u, 1, 10}}, Manipulate[x[u], control]]]
This
con = {u, 1, 10};
Manipulate[
u,
Evaluate#con
]
does work. I suppose it doesn't work without the Evaluate because
Attributes[Manipulate]
shows that Manipulate has the attribute HoldAll (but I may be wrong). To see the effect of this attribute, try this:
SetAttributes[f, HoldAll]
f[con]
f[Evaluate#con]
g[con]
(*
f[con]
f[{u, 1, 10}]
g[{u, 1, 10}]
*)
Thus, it appears that due to the HoldAll atribute, Manipulate simply does not see "inside" con unless you explicitly evaluate it.
I'm sure this is very simple, but I ask Mathematica for the characteristic polynomial of an equation, as follows:
m={
{0, n, 0, c1},
{R, 0, 4, c2},
{0, R, 0, 0},
{0, 0, R, c4}
}
CharacteristicPolynomial[m,x]
Now, I would like to save the returned polynomial as a function, so I can later call it (presumably with something like f[1]). Alas, I've been unable to figure out how to do this.
This is fairly straightforward. Simply do this
f[x_] = CharacteristicPolynomial[m,x]
Note the use of Set (=) not SetDelayed (:=) which forces CharacteristicPolynomial to be evaluated once. If you used SetDelayed, then it would be evaluated every time f is evaluated.
Hi I am using Mathematica 5.2. Suppose I have an array list like
In[2]:=lst=Tuples[{0,1},4]
Out[2]={{0,0,0,0},{0,0,0,1},{0,0,1,0},{0,0,1,1},
{0,1,0,0},{0,1,0,1},{0,1,1,0},{0,1,1,1},
{1,0,0,0},{1,0,0,1},{1,0,1,0},{1,0,1,1},
{1,1,0,0},{1,1,0,1},{1,1,1,0},{1,1,1,1}}
Now I want to get 16 arrays from the above array like st1={0,0,0,0}; st2={0,0,0,1}, st3={0,0,1,0}...
How can I get these array lists using a loop. Because if the no. of elements of the above array named lst become larger then it will not be a wise decision to take each of the element of the array lst separately and give their name separately. I tried this like the following way but it is not working...
Do[st[i]=lst[[i]],{i,1,16}]
Plz some body help me in this problem...
It does work, but what you create are the so-called indexed variables. You should access them also using the index, for example:
In[4]:= {st[1], st[2], st[3]}
Out[4]= {{0, 0, 0}, {0, 0, 1}, {0, 1, 0}}
I think what you are trying to do could be done by:
lst = Tuples[{0, 1}, 4];
Table[Evaluate[Symbol["lst" <> ToString[i]]] = lst[[i]], {i, Length#lst}]
So that
lst1 == {0,0,0,0}
But this is not a useful way to manage vars in Mathematica.
Edit
I'll try to show you why having vars lst1,lst2 .. is not useful, and is against the "Mathematica way".
Mathematica works better by applying functions to objects. For example, suppose you want to work with EuclideanDistance. You have a point {1,2,3,4} in R4, and you want to calculate the nearest point from your set to this point.
This is easily done by
eds = EuclideanDistance[{1, 2, 3, 4}, #] & /# Tuples[{0, 1}, 4]
And the nearest point distance is simply:
min = Min[eds]
If you want to know which point/s are the nearest ones, you can do:
Select[lst, EuclideanDistance[{1, 2, 3, 4}, #] == min &]
Now, try to do that same things with your intended lst1,lst2 .. asignments, and you will find it, although not impossible, very,very convoluted.
Edit
BTW, once you have
lst = Tuples[{0, 1}, 4];
You can access each element of the list just by typing
lst[[1]]
etc. In case you need to loop. But again, loops are NOT the Mathematica way. For example, if you want to get another list, with your elements normalized, don't loop and just do:
lstNorm = Norm /# lst
Which is cleaner and quicker than
Do[st[i] = Norm#lst[[i]], {i, 1, 16}]
You will find that defining downvalues (like st[i]) above) is useful when solving equations, but besides that many operations that in other languages are done using arrays, in Mathematica are better carried out by using lists.
Edit
Answering your comment actually I need each element of array lst to find the value of function such as f[x,y,z,k]=x-y+z+k. Such function may be
(#1 - #2 + #3 + #4) & ### lst
or
(#[[1]] - #[[2]] + #[[3]] + #[[4]]) & /# lst
Out:
{0, 1, 1, 2, -1, 0, 0, 1, 1, 2, 2, 3, 0, 1, 1, 2}
HTH!
You can do this:
Table[
Evaluate[
Symbol["st" <> ToString#i]] = lst[[i]],
{i, 1, Length#lst}];
at the end of which try Names["st*"] to see that you now have st1 to st16 defined. You could also do this with MapIndexed, like so:
MapIndexed[(Evaluate#Symbol["sts" <> ToString~Apply~#2] = #1) &, lst]
after which Names["sts*"] shows again that it has worked. Both of these can be done using a loop if this is what you (but I do not see what it buys you).
On the other hand, this way, when you want to access one of them, you need to do something like Symbol["sts" <> ToString[4]]. Using what you have already done or something equivalent, eg,
Table[
Evaluate[stg[i]] = lst[[i]],{i, 1, Length#lst}]
you end up with stg[1], stg[2] etc, and you can access them much more easily by eg Table[stg[i],{i,1,Length#lst}]
You can see what has been defined by ?stg or in more detail by DownValues[stg].
Or is it something else you want?
Leonid linked to a tutorial, which I suggest you read, by the way.
There are N ways of doing this, though like belisarius I have my doubts about your approach. Nonetheless, the easiest way I've found to manage things like this is to use what Mathematica calls "pure functions", like so:
In[1]:= lst = Tuples[{0,1}, 4];
In[2]:= With[{setter = (st[#1] = #2) &},
Do[setter[i, lst[[i]]], {i, Length#lst}]];
Doing it this way, the evaluation rules for special do just what you want. However, I'd approach this without a loop at all, just using a single definition:
In[3]:= ClearAll[st] (* Clearing the existing definitions is important! *)
In[4]:= st[i_Integer] := lst[[i]]
I think if you provide more detail about what you're trying to accomplish, we'll be able to provide more useful advice.
EDIT: Leonid Shifrin comments that if you change the definition of lst after the fact, the change will also affect st. You can avoid this by using With in the way he describes:
With[{rhs = lst},
st[i_Integer] := rhs[[i]]];
I don't know which will be more useful given what you're trying to do, but it's an important point either way.
Maybe something like this?
MapThread[Set, {Array[st, Length#lst], lst}];
For example:
{st[1], st[10], st[16]}
Out[14]= {{0, 0, 0, 0}, {1, 0, 0, 1}, {1, 1, 1, 1}}
I've encountered a problem while trying to use the answer from a NDSolve in two separate plot commands. To illustrate the problem, I'll use a simple differential equation and only one plot command. If I write something like this:
{Plot[x[t], {t, 0, 10}], x[4]}
/. NDSolve[{x'[s] == - x[s], x[0] == 1}, x, {s, 0, 10}]
It solves the equation and calculates x[4] with no problem, but the plot turns empty, and I have no idea why.
In my actual problem, my equation is a quite complicated system for several functions, and instead of x[4] I draw a parametric plot of the solved functions. I ultimately intend to include all this in a Manipulate statement so I don't want the NDSolve statement to appear more than once (takes too long) and I can't just calculate it in advance (since it has a lot of parameters).
Edit: I would like to clarify and expand my question: What I actually want to do is to include my plotting statement in a Manipulate statement in the following way:
Manipulate[{Plot[x[t], {t, 0, 10}], x[4]}
/. NDSolve[{x'[s] == - a*x[s], x[0] == 1}, x, {s, 0, 10}]
,{{a,1},0,5}]
Since only the Manipulate statement gives value to the parameter a, I can't calculate the answer to the NDSolve beforehand. Also, since my actual equation system is very complicated and non-linear, I can't use the symbolic function DSolve.
Sorry if it wasn't clear before.
Your problem is that Plot[] does some funny things to make plotting more convenient, and one of the things it does is just not plot things it can't evaluate numerically. So in the expression you posted,
Plot[x[t], {t, 0, 10}]
just goes ahead and evaluates before doing the rule substitution with the solution from NDSolve, producing a graphics object of an empty plot. That graphics object contains no reference to x, so there's nothing to substitute for.
You want to make sure the substitution is done before the plotting. If you also want to make sure the substitution can be done in multiple places, you want to store the solution into a variable.
sol = NDSolve[{x'[s] == - x[s], x[0] == 1}, x, {s, 0, 10}];
{Plot[Evaluate[x[t] /. sol], {t, 0, 10}], x[4] /. sol}
The Evaluate[] in the Plot makes sure that Mathematica only does the substitution once, instead of once for each plot point. It's not important for a simple rule substitution like this, but it's a good habit to use it in case you ever want to plot something more complicated.
In order to make this work in a Manipulate, the simple way is to use With[], which is one of Mathematica's scoping constructs; it's the one to use where you just want to substitute something in without using it as variable you can mutate.
For example,
Manipulate[
With[{sol = NDSolve[{x'[s] == - x[s], x[0] == 1}, x, {s, 0, 10}]},
{Plot[x[t] /. sol // Evaluate, {t, 0, 10}, PlotRange -> {0, 1}],
x[4] /. sol}],
{{a, 1}, {0, 5}}]
Use the PlotRange option to keep the y-axis fixed; otherwise things will jump around in an ugly way as the value of a changes. When you do more complex things with Manipulate, there are a number of options for controlling the speed of updates, which can be important if your ODE is complicated enough that it takes a while to solve.
Meanwhile, I found another way to do this. It's less elegant, but it only uses one substitution so I've thought I'll post it here also.
The idea is to use Hold on the Plot so it wouldn't get evaluated, do the rule substitution and then ReleaseHold, just before the Manipulate.
Manipulate[ReleaseHold[
Hold[ {Plot[x[t], {t, 0, 10}, PlotRange -> {0, 1}], x[4]} ]
/.NDSolve[{x'[s] == -a x[s], x[0] == 1}, x, {s, 0, 10}]
], {{a, 1}, 0, 5}]