Message Boards Message Boards

2 Replies
2 Total Likes
View groups...
Share this post:

At what level does ReplaceAll pattern match for rule execution

As a Mathematica beginner reading through Paul Wellin's Mathematica book, I ran across a very interesting example

 {{3, 4}, {7, 2}, {1, 5}} /. {x_, y_} :> {y, x}

which returns the elements of each ordered pair exchanged resulting in {{4, 3}, {2, 7}, {5, 1}}

I thought it would be interesting to generalize it for handling "rows" with two or more columns without regard to how many columns each row had (or the number of rows in the list) and using a rule something like

  {x_, y_, z___} :>{y, x, z}

But, I quickly ran into a problem which has caused me to realize I do not understand what Mathematica is going to do in general. Not only did my rule not work, it failed in a way not predictable to me. Simplifying problem with Wellin's example modified to be a 2 x 2 matrix instead of a 3 x 2 matrix:

  {{3, 4}, {7, 2}} /. {x_, y_} :> {y, x}

results in {{7, 2}, {3, 4}}

That is, Mathematica no longer exchanges the elements within each sublist, it exchanges the sublists. This is confusing to me because I expected if a rule works with a simplified sample problem it will work with generalized versions. That seems not to be the case.

Why is Mathematica doing this and how should be expression be coded to work as I had expected?

POSTED BY: Lawrence Winkler
2 Replies

Thank you. I kind of expected an answer similar to yours. This leads me to another question, which was the critical one lurking but unstated.

How do you Mathematica Pros write bullet-proof code? ReplaceAll (/.) and ReplaceRepeated (//.) are used extensively in the sample code I've seen, but my simple example suggests to me that I have to exercise tight control over data structures submitted to my own processes in order to prevent possibly undetected and absurd results.

POSTED BY: Lawrence Winkler

If you want to always replace at second level only, you can use

       Replace[{{3, 4}, {7, 2}, {1, 5}}, {x_, y_} :> {y, x}, {2}]
       (*  {{4, 3}, {2, 7}, {5, 1}}  *)
       Replace[{{3, 4}, {7, 2}}, {x_, y_} :> {y, x}, {2}]
       (*  {{4, 3}, {2, 7}}  *)

The reason why ReplaceAll[{{3, 4}, {7, 2}}, {x_, y_} :> {y, x}] produced {{7, 2}, {3, 4}} and not {{4, 3}, {2, 7}} is because Mathematica matched {x_,y_} with {3, 4}, {7, 2} as a whole, hence x_ matched {3, 4} and y_ matched {7, 2} and so it returned these flipped (ReplaceAll stops once it finds a match and starts from first level). In the first case ReplaceAll[{{3, 4}, {7, 2}, {1, 5}}, {x_, y_} :> {y, x}] it worked, since Mathematica tried first to match at first level, and could not (not possible to match {a,b,c} with {x_,y_}, so it went to second level, and found the pattern it can match to, and hence it worked then.

So if you want to always match at specific level, you can use Replace with specific level and be explicit about it. Look up help for Replace. It makes a difference if ones uses level {n} vs. n also. {n} says only level n, while n means level 1 to n.

POSTED BY: Nasser M. Abbasi
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
or Discard

Group Abstract Group Abstract