9
$\begingroup$

Here is my code.

{2, 9, 3, 16, 81, 0.09} //. {x_Integer -> Sqrt[x]}

The pop-up message ReplaceRepeated::rrlim suggests that this rule can be applied an infinite number of times.

I am supposed to get {Sqrt[2],Sqrt[3],Sqrt[3],Sqrt[2],Sqrt[3],0.09}

What's wrong with my code here?

$\endgroup$
  • 3
    $\begingroup$ Hint: After the first pass, what is the head of the first list element's (Sqrt[2]) contents? $\endgroup$ – ciao Feb 29 at 10:16
  • 1
    $\begingroup$ @ciao, Power. How to make it work ? {Sqrt[2],Sqrt[3],Sqrt[3],Sqrt[2],Sqrt[3],0.09} $\endgroup$ – kile Feb 29 at 10:18
  • 2
    $\begingroup$ One way might be {y : Power[_, _] -> y, x_Integer -> Sqrt[x]} for the rules. More importantly, do you see why the example evaluates infinitely? $\endgroup$ – ciao Feb 29 at 10:20
  • 2
    $\begingroup$ @ciao,x_Integer still assumes Sqrt[2] and Sqrt[3] are Integer. $\endgroup$ – kile Feb 29 at 10:26
  • 4
    $\begingroup$ Perhaps a better response to @OkkesDulgerci would be to point out that his code changes 9 to 3, not to Sqrt[3] as desired. $\endgroup$ – Michael E2 Feb 29 at 14:36
12
$\begingroup$

The documentation specifically states:

You should be very careful to avoid infinite loops when you use the //. operator. The command x //. x -> x + 1 will, for example, lead to an infinite loop.

Since only the first rule that matches is applied to a given expression you can, as ciao commented, use:

{2, 9, 3, 16, 81, 0.09} //. {skip_Power :> skip, x_Integer :> Sqrt[x]}
{Sqrt[2], Sqrt[3], Sqrt[3], Sqrt[2], Sqrt[3], 0.09}

Recommended reading:

| improve this answer | |
$\endgroup$
  • 1
    $\begingroup$ Very nice solution, exactly as was asked in OP. Maybe one can add that some confusion arises due to the fact that Replace has levelspec option, whereas ReplaceAll and ReplceRepeated---no. $\endgroup$ – yarchik Mar 1 at 9:16
  • 1
    $\begingroup$ A slight generalization: list //. {x_Integer :> Sqrt[x], skip_?NumericQ :> With[{x = Simplify[skip]}, If[IntegerQ[x], Sqrt[x], skip]]}. In case other numeric expression are in the original list. $\endgroup$ – Michael E2 Mar 1 at 18:04
14
$\begingroup$

I think the proper answer here is to use FixedPoint, because //. dives in to the expression. Sqrt[2] contains an integer inside so it replaces it over and over.

FixedPoint[Replace[#, x_Integer :> Sqrt[x], {1}] &, {2, 9, 3, 16, 81, 0.09}]

Notice that I specifically said that it should replace at level 1.

| improve this answer | |
$\endgroup$
  • 2
    $\begingroup$ Can you please point to the place in the documentation where it is written that //. should dive into subexpressions. $\endgroup$ – yarchik Feb 29 at 11:28
  • $\begingroup$ It is basically doing /. repeatedly until it doesn't change any more. The documentation of /. (ReplaceAll). Which has as first line: applies a rule or list of rules in an attempt to transform each subpart of an expression expr. $\endgroup$ – SHuisman Feb 29 at 11:30
  • 3
    $\begingroup$ @yarchik "expr//.rules effectively applies /. repeatedly, until the results it gets no longer change." (Docs for ReplaceRepeated) See also the documentation for the error message $\endgroup$ – Michael E2 Feb 29 at 14:38
  • 1
    $\begingroup$ @MichaelE2 Why then this {2, 9, 3, 16, 81, 0.09} //. {x_ /; (Head[x] == Integer) -> Sqrt[x]} does not work? Sorry, if it is something obvious. $\endgroup$ – yarchik Feb 29 at 18:12
  • 2
    $\begingroup$ it works, but again, it dives deeper in to the expression because you're using //. (or /.) $\endgroup$ – SHuisman Feb 29 at 20:54

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