# Unexpected behavior of rule-replacing with string concatenation [closed]

Here's the code.

Clear[x,y,z];
{x,y,z} /. x_ :> ("^_^" <> ToString[x])


I get the result ^_^{x, y, z}, which is not what I intended. However, I want to have {^_^x, ^_^y, ^_^z}. I found the problem occurred was related to the appearance of <> or ToString.

The problem seems so basic, but I've been debugging for a long while, still having not got the right answer.

-

## closed as off-topic by Mr.Wizard♦Aug 14 '14 at 5:06

This question appears to be off-topic. The users who voted to close gave this specific reason:

• "This question arises due to a simple mistake such as a trivial syntax error, incorrect capitalization, spelling mistake, or other typographical error and is unlikely to help any future visitors, or else it is easily found in the documentation." – Mr.Wizard
If this question can be reworded to fit the rules in the help center, please edit the question.

This is because Mathematica looks for the largest piece of the expression that matches the pattern. Your pattern is x_, which means every conceivable expression there is will match that pattern. As a result, the entire expression {x,y,z} will be matched as it is the largest matching piece (x, y, and z won't be matched because they are smaller pieces compared to the entire list). Therefore, {x,y,z} will become "{x,y,z}" from ToString, after which it will join with "^_^", hence your result:

{x, y, z} /. x_ :> ("^_^" <> ToString[x]) // FullForm
(* "^_^{x, y, z}" *)


To avoid this problem, you have to modify the level (or "depth", so to speak) of the replacement so that the pattern does not match the entire list, but only the elements within that list. This can be done using Replace (instead of ReplaceAll i.e. /.). The arguments of this replacement is pretty much the same as that of ReplaceAll, except you have the argument {1} at the end. This means that your operation will only replace elements in the 1st level of the expression. In the context of a list, this refers to the elements of a list, and not the list itself (which is actually level 0). Hence, only the list elements--x, y, and z--are replaced in this case:

Replace[{x, y, z}, x_ :> ("^_^" <> ToString[x]), {1}]
(* {^_^x,^_^y,^_^z} *)


Sidenote: the reason your {x,y,z} /.x_->3 x evaluates to {3 x,3 y,3 z} is because in this case the pattern will match the entire list (just as it did the example in your question). That means the entire list will be multiplied by 3 i.e. it will become 3 {x, y, z}.

However, arithmetic operations in Mathematica typically "threads", or "distributes" (see the attribute Listable) to every elements in that list. Hence, multiplying a list by 3 is the same thing as multiplying each element of that list by 3, which results in {3 x,3 y,3 z} as you observed.

-
{{z}, {z, w}} /. x_?((! ListQ@# && ! # === List) &) -> f[x] :) –  belisarius Aug 14 '14 at 5:14
o.O. Very interesting that 2 tests are needed to avoid replacing Lists (though I see why there should be). I'm assuming this will make any ReplaceAll listable? –  seismatica Aug 14 '14 at 5:32
@belisarius I would use: {{z}, {z, w}} /. x : Except[List | _List] :> f[x] –  Mr.Wizard Aug 14 '14 at 6:14
Love it! I was using Except[List | _Symbol] and I was thinking "Hmm, how can I make this more general?" –  seismatica Aug 14 '14 at 6:16
I don't know about (1) and (2), but I think (3) is true. There is a very readable PDF from the Mathematica Journal called "Demystifying Rules", which you can download here. It helped me understand rules a lot better. –  seismatica Aug 14 '14 at 6:29
Replace[{x, y, z}, x_ :> ("^_^" <> ToString[x]), Infinity]

-
Why {x,y,z} /.x_->3 x yields the ideal result {3 x,3 y,3 z} but this case isn't? –  Eric Aug 14 '14 at 4:44
They seem so similar! –  Eric Aug 14 '14 at 4:47
@Eric Times in 3 x is Listable. Look up Listable in the documentation. –  Mr.Wizard Aug 14 '14 at 5:56
I see. Thanks!! –  Eric Aug 14 '14 at 6:04

What goes wrong

The help page of ReplaceAll explains why your code is not doing what you want.

ReplaceAll (/.) applies a rule or list of rules in an attempt to transform each subpart of an expression expr

In the end it applies the rule to the largest subpart it can match.

The expression {x,y,z} has two levels (depth of two).

{x, y, z} // FullForm

List[x,y,z]


Your rule x_ :> ("^_^" <> ToString[x]) will match the whole expression.

How to fix it

You want to apply your rule only at level 1. For that you can use

Replace[{x, y, z}, x_ :> ("^_^" <> ToString[x]), {1}]


{"^^x", "^^y", "^_^z"}

, very similar to what Chenminqi suggested. Can you see the difference? I suggest you experiment a bit with levels. Try for example the list {{x, y}, z} and see what happens and how you can change the dept of the depth in replace.

Remark

This also explains why

x /. x_ :> ("^_^" <> ToString[x])


gives "^_^x", as you expected. The expression x has only one level (0). The rule is applied just once, giving the output that you expected.

-