“Strange” behavior of Rule

According to the Help

lhs->rhs evaluates rhs immediately.

How to understand the output of the following code?

ClearAll@x;
{1, 3.5} /. x_?IntegerQ -> {x}

Output is

{{1},3.5}

Since Mathematica evaluate the rhs immediately, I think the “correct” output should be this

{{x},3.5}

And of course, if x has OwnValues, the output will be changed.

x=”why”;
{1, 3.5} /. x_?IntegerQ -> {x}

Output is

{{"why"},3.5}

As expected.

In my opinion, the two examples expose the contradictions.

In the first one, Rule behaves like RuleDelayed; it relates the local x with global x. (The color of the two variables in front-end tells me this.) But in the second one, Rule makes a clear distinction between the local and global. (There are also something similar between Set and SetDelayed)

Why does this happen? Did I misunderstand the mechanism?

Update

What I'm really confusing is Why sometimes Mathematica does not distinguish the global x and the local x in Rule.

Solution

As Aky has metioned in his comments and answer. The documentiation says,

Symbols that occur as pattern names in lhs are treated as local to the rule. This is true when the symbols appear on the right-hand side of /; conditions in lhs , and when the symbols appear anywhere in rhs , even inside other scoping constructs.

So if x doesn't have OwnValues, then the Head of x is Symbol and the name of x is the same as pattern name, as the documentation said , Mathematica will treat the two 'x's as the same. If x has OwnValues,take x=y for example, (Head of y is also Symbol) Even if x (actually y) is Symbol, the "name" of x is y which is different from the pattern name.

So in the following case,

x=y;
{1,3.5}/.x_?IntegerQ->{x}

Mathematica will return {{y},3.5} not {{1},3.5}.

Thanks for everyone's attention:)

• I changed DownValues to OwnValues as x = "why" sets an OwnValue not a DownValue. – rcollyer May 8 '13 at 12:21
• X=”why”;x="why"; ClearAll@x; {1, 3.5} /. x_?IntegerQ :> {x} – HyperGroups May 8 '13 at 12:23
• @rcollyer Thanks for the correction:) – luyuwuli May 8 '13 at 12:26
• @HyperGroups I know :> will behave as expected, but I just want to figure out the mechanism of ->. – luyuwuli May 8 '13 at 12:28
• As the documentation says, "Symbols that occur as pattern names in lhs are treated as local to the rule." So the x is left as part of the rule (assuming that on the rhs it didn't first evaluate to something else, due to a global rule) – Aky May 8 '13 at 13:15

I don't think there's a contradiction.

The documentation for Rule says

Symbols that occur as pattern names in lhs are treated as local to the rule.

and as you've already pointed out,

lhs -> rhs evaluates rhs immediately

In

ClearAll@x;
{1, 3.5} /. x_?IntegerQ -> {x}

the rule's rhs evaluates first, but there's no global rule associated with x, so the rule remains as x_?IntegerQ -> {x}, and the x everywhere in the rule is local to it.

In

x = "why";
{1, 3.5} /. x_?IntegerQ -> {x}

the rule's rhs evaluates to "why", and the rule becomes x_?IntegerQ ->{"why"}.

• Yes, it's my carelessness. Thank you:) – luyuwuli May 8 '13 at 13:40

Perhaps it will seem clearer if the FullForm of the rule is examined. In the first example below, we see that the value of x is the RHS of the rule. So we should expect any integer to be replaced by {2}.

x = 2;
x_?IntegerQ -> {x} // FullForm
Rule[PatternTest[Pattern[x, Blank[]], IntegerQ], List]

Here, if we clear x, the RHS of the rule is {x}. As @Aky pointed out in a comment, the documentation implies that in this rule the symbol x will represent the pattern match. So we should expect any integer to be replaced by a list containing that integer.

Clear[x];
x_?IntegerQ -> {x} // FullForm
Rule[PatternTest[Pattern[x, Blank[]], IntegerQ], List[x]]

One might wish to compare the above with RuleDelayed. Even if x has an ownvalue, the RHS is {x}. So this rule will behave like the previous one.

x = 2;
x_?IntegerQ :> {x} // FullForm
RuleDelayed[PatternTest[Pattern[x, Blank[]], IntegerQ], List[x]]
• Than you very much. It's my carelessness. Next time, I will carefully read the documentation before post my question. Since Aky has pointed it out in the comment first and also posted the answer. I'll accept his. (Both of you post your answers almost at the same time. At that moment, I was writing the comment.) – luyuwuli May 8 '13 at 13:48
• That's fine. I thought perhaps Aky was not going to post an answer, so I impatiently went ahead :), having time on my hands at present. – Michael E2 May 8 '13 at 13:52

I don't know why it works that way, and you have the same issue with f[x_]={x}. You will find code here that defines new operators that work like x_?IntegerQ->{X} and f[x_]={x} except the new operators do what you expected.

• Aky's comment (and many others' including mime) has solved the issue. I'll edit my post to include the answer in the end. BTW, thank you for the link, I'll study that:) – luyuwuli May 9 '13 at 11:45

Note that your first example is not contradictory with the immediate evaluation of the rhs.
For example, if you try :

ClearAll[x, y]
x = y
{1, 3.5} /. y_?IntegerQ -> {x}

you get {{1}, 3.5}.

This means that the rhs is really evaluated

• I don't think this solve my confusion. Since the color of the local "y" is different from golbal "y". I think Mathematica should not build bridge between the two 'y's. I mean I would rather get {{y}, 3.5} not {{1},3.5}. – luyuwuli May 8 '13 at 12:42
• agree it doesn't explain everything. Hope someone will go further. – andre314 May 8 '13 at 13:09