2
$\begingroup$
{"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?

$\endgroup$
7
  • $\begingroup$ Try evaluating StringReverse[s] on its own, without s having a value. $\endgroup$
    – Szabolcs
    Commented Aug 19, 2017 at 10:16
  • $\begingroup$ @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... $\endgroup$ Commented Aug 19, 2017 at 10:45
  • $\begingroup$ 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]]]. $\endgroup$
    – Szabolcs
    Commented Aug 19, 2017 at 11:06
  • $\begingroup$ 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. $\endgroup$
    – Szabolcs
    Commented Aug 19, 2017 at 11:09
  • $\begingroup$ @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... $\endgroup$ Commented Aug 19, 2017 at 18:03

1 Answer 1

5
$\begingroup$

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}

$\endgroup$
3
  • $\begingroup$ 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... $\endgroup$ Commented Aug 19, 2017 at 18:00
  • $\begingroup$ @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[]. $\endgroup$ Commented Aug 19, 2017 at 18:35
  • $\begingroup$ @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. $\endgroup$
    – david
    Commented Aug 19, 2017 at 19:11

Not the answer you're looking for? Browse other questions tagged or ask your own question.