The Replace function is greatly under appriciated because the Wolfram
Research documentation gives very little discussion of what it can do. After
reading the documentation on Replace you get the impression that it tries to
use replacement rules on an entire expression and nothing more.

The cell below demonstrates this basic use of Replace.  In this case the
expression (demo) matches the form for the replacement rule. The rule is used
once and that is the end of it.

Clear[a] ;  demo = {0, {1, {2, {3, {4, {5, {6, {7, 7}}}}}}}} ;    Replace[demo, {x_, y__}  {x, a, y}]

{0, a, {1, {2, {3, {4, {5, {6, {7, 7}}}}}}}}

The basic use of Replace isn't very useful. The power of Replace lies in  use of it's third argument where a level specification is given. In the next cell the replacement is used at level 1 down to the  atoms and all levels between.

Replace[demo, {x_, y__}  {x, a, y}, -1]

{0, {1, a, {2, a, {3, a, {4, a, {5, a, {6, a, {7, a, 7}}}}}}}}

In the next case the replacement is only performed at level 3.

Replace[demo, {x_, y__}  {x, a, y}, {3}]

{0, {1, {2, {3, a, {4, {5, {6, {7, 7}}}}}}}}

The next cell uses the replacement on levels 2, 3, and 4.  As explained below
the replacements start at the deepest level (level 4 in this case) and works
up to the higher levels.

Replace[demo, {x_, y__}  {x, a, y}, {2, 4}]

{0, {1, {2, a, {3, a, {4, a, {5, {6, {7, 7}}}}}}}}

When the third argument of Replace is  -6  the replacement start with
expressions with a depth of 6 and works up to level 1.

Replace[demo, {x_, y__}  {x, a, y}, -6]

{0, {1, a, {2, a, {3, a, {4, {5, {6, {7, 7}}}}}}}}

When the third argument of Replace is {-7,4} the replacement start at level 4
and work up to expressions with a depth of 7.

Replace[demo, {x_, y__}  {x, a, y}, {-7, 4}]

{0, {1, {2, a, {3, a, {4, a, {5, {6, {7, 7}}}}}}}}

We can give Replace a list of replacement rules as in the next cell.  We  could use (lhs:→rhs) instead of (lhs→rhs) and the  difference between the two is discussed in the section on Rule instead of RuleDelayed.

Replace[w + x + y + z, {x2x, y3y}, {0, ∞}]

w + 2 x + 3 y + z

Once Replace changes a part of an expression no further replacements are  made on that portion of the expression or any of it's subparts.  For example  the rule in the next cell is only used once on each logrithm.  Normally  ReplaceRepeated would be used to fully expand the logrithms, but you could  use FixedPoint and Replace to fully expand these logrithms (I won't do that  here).

I don't provide further examples, but any combination of pattern matching  constructs can be used on the left side of rules given to Replace.  Nuances  of pattern matching are discussed in another section.

Replace[Log[d p q r] Log[a b c d], Log[a_  b_] Log[a] + Log[b], {0, ∞}]

(Log[a] + Log[b c d]) (Log[d] + Log[p q r])

The order of matching patterns and making replacements

I learned from Allan Hayes that Replace attempts replacements starting at the
deepest level allowed by the level specification and works its way up to
higher levels. Allan also explained that Replace doesn't evaluate the
expression between replacements. Replace doesn't have a holding attribute, so
it's arguments evaluate before doing replacements. The demonstration and
explanation below is based on an example Allan Hayes once provided.

Clear["Global`*"] ;  rls = {a1 + b2baab, b1 + b2b12, a1b1} ;  a2 = b2 ;  h[b1 + b2] = bb ;

Replace[h[a1 + a2], rls, {1, 2}]


The important parts of evaluation above are as follows:
The first  argument of Replace evaluates as  h[a1+a2]→h[a1+b2]  since  (a2=b2).
Next Replace starts replacements at the deepest level, so the first  replacement used on  h[a1+b2] is (a1→b1) resulting in  h[b1+b2].  No  evaluation is conducted until Replacements are finished.  Moving up a level  the replacement (b1+b2→b12) is used and resuts in  h[b12]  which is the final expression.  Notice we had h[b1+b2] after the first  replacement, but the definition for h[b1+b2] wasn't used.  Once replacements  started nothing evaluated until all replacements were finished.

ReplaceAll and ReplaceRepeated make replacements starting at the top level and work down, but Replace is  different since it starts replacements at the deeper levels and works it's  way up.

The next input shows how you can easily see the order that Replace  tries replacements on different parts of an expression.

Replace[h[f1[a1], f2[e][a2]], (a_/;Print[a] 0), {0, ∞}]





h[f1[a1], f2[e][b2]]

h[f1[a1], f2[e][b2]]

Replace makes replacements starting at the deepest level, so in the next cell
Log[x] is changed to Log[a x].

 Replace[x^(1/2) + 2x^3 - Log[x]/y, {xa x, Log[x] Log[x + 1]}, {0, ∞}]

2 a^3 x^3 + (a x)^(1/2) - Log[a x]/y

Since ReplaceAll starts making replacements at the highest level, Log[x] in the next cell  is changed to Log[x+1].

 x^(1/2) + 2x^3 - Log[x]/y/.{xa x, Log[x] Log[x + 1]}

2 a^3 x^3 + (a x)^(1/2) - Log[1 + x]/y

Heads Option

Replace has a 'Heads' option which controls whether it consideres making
replacements on the heads of expressions.  The default setting is (Heads
→False).  The next cell shows the order that different parts of the
expression are considered for replacement when replacing heads is allowed.

Replace[h[f1[a1], f2[e][a2]], (a_/;Print[a] 0), {0, ∞}, HeadsTrue]










h[f1[a1], f2[e][b2]]

h[f1[a1], f2[e][b2]]

Created by Mathematica  (May 16, 2004)

Back to Ted’s Tricks index page