# Rule vs RuleDelayed in the context of StringReverse [duplicate]

{"test", 3} /. s_String :> StringReverse[s]
{"test", 3} /. s_String -> StringReverse[s]


The second line gives the error:

StringReverse: String expected at position 1 in StringReverse[s]

Question: why does it give the error with Rule, but not RuleDelayed?

EDIT: I noticed that {3, 4} /. s_ -> Sin[s] // N works without error. What is the difference?

• Try evaluating StringReverse[s] on its own, without s having a value. – Szabolcs Aug 19 '17 at 10:16
• @Szabolcs I think my question is different; what I didn't understand was that the rhs of a rule is calculated first... so the line is not evaluated strictly from left to right... – GambitSquared Aug 19 '17 at 10:45
• There is no difference at all in this regard between Set and Rule. In fact the LHS is evaluated first, as you assumed. But LHS of the rule is only s_String. The /. and what comes to the left of that is not part of the rule. It's the reverse: The rule is part of the /.. Look at the full form: ReplaceAll[{"test", 3}, Rule[s_String, StringReverse[s]]]. – Szabolcs Aug 19 '17 at 11:06
• Since neither Rule nor ReplaceAll have any (relevant) Hold* attributes, the standard evaluation sequence is followed: 1. left to right, starting with the head and continuing with arguments. 2. then apply definitions associated with the head. This means that StringReverse[s] gets evaluated before ReplaceAll has a chance to do anything with it. – Szabolcs Aug 19 '17 at 11:09
• @Szabolcs Why does this {3, 4} /. x_ -> Sin[x] // N work without error then? Here Sin[x] is evaluated before Mathematica knows x is a real number... – GambitSquared Aug 19 '17 at 18:03

## 1 Answer

If you don't use RuleDelayed, StringReverse is executed before the rest of the function. And because it expects a string as argument (and not the symbol s) it complains and goes on strike.

You can see this with

TracePrint[{"test", 3} /. s_String -> StringReverse[s], _StringReverse]


And also with

{"test", 3} /. s_String -> StringReverse["ab"]


{"ba", 3}

• Why does it actually work in this case: {3, 4} /. x_ -> Sin[x] // N ? x is not know to be a real number yet here is well... – GambitSquared Aug 19 '17 at 18:00
• @Gambit, once more: when in doubt as to how something gets evaluated, wrap the expression in Hold[] and look at the FullForm[]: FullForm[Hold[{3, 4} /. x_ -> Sin[x] // N]]. You will then see that the replacement is done before the sines are seen by N[]. – J. M.'s ennui Aug 19 '17 at 18:35
• @GambitSquared, Also, note that StringReverse requires a string or list of strings as an argument,otherwise it will generate the message you see. Sin can accept numeric or symbolic arguments. – david Aug 19 '17 at 19:11