Re: Confused about replacement rules
- To: mathgroup at smc.vnet.net
- Subject: [mg7194] Re: Confused about replacement rules
- From: villegas (Robert Villegas)
- Date: Wed, 14 May 1997 01:11:30 -0400 (EDT)
- Organization: Wolfram Research, Inc.
- Sender: owner-wri-mathgroup at wolfram.com
This is a common point of confusion when ReplaceAll (as opposed to Replace) is used to apply two or more rules. In expr /. {rule1, ..., rulen} it is NOT the case that rule1 is tried on all subexpressions, then rule2, and so on. Instead, it is the parts of the expression (from the top down, in lexicographic order by position) that are the first dimension of the ReplaceAll operation, and the rules that are the second dimension. The pattern-matcher starts at level 0 (i.e the entire expression) and tries all the rules in order on it. The pattern-matcher applies the first rule that matches and then ceases. If no rule applies to the whole, the pattern-matcher moves on to level 1 (head and then elements in order), trying all rules on each given target before moving on to the next target. Again, once a rewrite is performed on a part, the pattern-matcher never visits it or its subexpressions again. After visiting level 1, the pattern-matcher moves on to level 2 (the elements of any parts it did not rewrite during its visit to level 1). And so on through the bottom-most level, the atoms. The confusing point is that after a part is transformed, it and its subexpressions aren't visited any more, even though they might contain plenty of matches of the rules. This is especially confusing when a rule applies to a part but ends up not changing it, which happened to the entire expression (level 0 -- the pattern-matcher's first stop) in your case. One way around this is to do cumulative ReplaceAll operations instead of a single one, effectively changing the first dimension of the operation to the rules and the second dimension to the parts of the expression. Fold[ReplaceAll, expr, {rule1, ..., rulen}] You can use ReplaceRepeated if the rewrites might themselves contain things that can be transformed: Fold[ReplaceRepeated, expr, {rule1, ..., rulen}] (and maybe even do a FixedPoint of the Fold operation if one rule might introduce more matches of the previous rules). A useful debugging technique to use when your rules go awry is to print the value that matched the pattern. For instance, In[15]:= rules = {x_^2 :> (Print["x = ", x]; a), expr_ :> (Print["expr = ", expr]; Expand[expr])} 2 Out[15]= {(x_) :> (Print[x = , x]; a), expr_ :> (Print[expr = , expr]; Expand[expr])} In[16]:= x (b + x) /. rules expr = x (b + x) 2 Out[16]= b x + x In[17]:= % /. rules 2 expr = b x + x 2 Out[17]= b x + x As you can now see, the second rule fired on the entire expression in In[17] but did not change it. After applying a rule to the whole expression, ReplaceAll stopped applying rules. If you have several rules intended to transform subexpressions, it is usually wise to avoid an all-encompassing pattern such as expr_ but instead to use specific patterns. Or if you can't avoid this then you might have to Map your replacement operation onto the elements of the expression, as you discovered. Robby Villegas