Say I have a list of Rules
rules = {a -> b, c -> d};
which I use throughout a notebook. Then, at one point, it makes sense to want the rules to apply before any other evaluations take place in an expression. Normally if you want something like this you would use
In[2]:= With[{a=b,c=d}, expr[a,b,c,d]]
Out[2]= expr[b, b, d, d]
How can I take rules
and insert it into the first argument of With
?
Edit
BothSome solutions fail do all that I was looking for - but I should have emphasised this point a little more. See the bold part above.
For example, let's look at
rules = {a -> {1, 2}, c -> 1};
If I use these vaules in With
, I get
In[10]:= With[{a={1,2},c=1}, Head/@{a,c}]
Out[10]= {List,Integer}
Some versions of WithRules
yield
In[11]:= WithRules[rules, Head/@{a,c}]
Out[11]= {Symbol, Symbol}
(Actually, I didn't notice that Andrew's answer had the Attribute HoldRest
- so it works just like I wanted.)
I have been using the following form of
WithRules
for a long time. Compared to the one posted by Andrew Moylan, it binds sequentially so that you can say e.g.WithRules[{a->b+1, b->2},expr]
and geta
expanded to3
:This was also posted as an answer to an unrelated question, and as noted there, it has been discussed (at least) a couple of times on usenet:
HTH
EDIT: Added a
ReleaseHold
,Hold
pair to keepexpr
unevaluated until the rules have been applied.One problem with Andrew's solution is that it maps the problem back to With, and that does not accept subscripted variables. So the following generates messages.
Given that
With
performs syntactic replacement on its body, we can set WithRules alternatively as follows:Then
Edit: Addressing valid concerns raised by Leonid, the following version would be safe:
Then
Edit 2: Even WithRules3 is not completely equivalent to Andrew's version:
You want to use Hold to build up your With statement. Here is one way; there may be a simpler:
Test it out:
(I used Print so that any bug involving me accidentally evaluating expr too early would be made obvious.)