Unexpected behavior using `ReplaceAll[]` for nested lists

ReplaceAll is way overused, and it can very easily lead to unexpected results (or bugs in your code) because it replaces at all levels. In fact, the example you show is one of the most common errors stemming from the misuse of ReplaceAll.

I recommend using ReplaceAll only when you know you need it, except for algebraic replacements.

Otherwise, use Replace:

Replace[{{1, "2"}, {2, "3"}}, {x_, _ } :> {x, "SOMETHING"}, {1}]

Make Replace your default choice unless you know why you need ReplaceAll, especially when developing packages (where robustness is a requirement).

Of course, when doing interactive work, a bit of sloppiness if forgivable :-) /. is just shorter to type.


The issue is that the provided pattern also matches the outer list. Therefore ReplaceAll[] replaces the outer list and stops (as there are no elements left).

To overcome this issue, Map[] must be used:

ReplaceAll[{x_, _} :> {x, "SOMETHING"}] /@ {{1, "2"}, {2, "3"}}