Re: RE: Behavior of ReplaceAll with Computed Results from a Conditional Test

*To*: mathgroup at smc.vnet.net*Subject*: [mg66802] Re: [mg66770] RE: [mg66745] Behavior of ReplaceAll with Computed Results from a Conditional Test*From*: "Chris Chiasson" <chris at chiasson.name>*Date*: Tue, 30 May 2006 05:49:52 -0400 (EDT)*References*: <200605291006.GAA07644@smc.vnet.net>*Sender*: owner-wri-mathgroup at wolfram.com

The delayed evaluation of all right hand sides until after all testing seems to happen when Condition is not the head of either the left or right hand side of a rule. testQ[x_Symbol,y_Symbol,z_Symbol]:=(Print["testing tuple: ",{x,y,z}]; If[x===z,seq=Unevaluated[Sequence[x^2,y]];True,False]) {{b,a,b},{a,b,c},{a,b,a}}/.{tuple___}/; testQ[tuple]\[RuleDelayed](Print["acting on tuple: ",{tuple}, " to write sequence: ",{seq}];{seq}) {{b,a,b},{a,b,c},{a,b, a}}/.{tuple___}\[RuleDelayed](Print["acting on tuple: ",{tuple}, " to write sequence: ",{seq}];{seq})/;testQ[tuple] {{b,a,b},{a,b,c},{a,b, a}}/.{tuple___}\[RuleDelayed](Print["acting on tuple: ",{tuple}, " to write sequence: ",{seq}];{seq}/;testQ[tuple]) Evaluate the above to see the results; then wrap the code in FullForm[Hold[]] to see the structure. The only change from the 2nd rule to the 3rd is the movement of "/;testQ[tuple]" inside the parenthesis. This has the effect of bringing it inside CompoundExpression, of which the infix form is usually a semicolon. Perhaps the semicolon in the short form of Condition indicates Condition is meant to become part of a preceeding (infix) CompoundExpression. On 5/29/06, David Park <djmp at earthlink.net> wrote: > I received several replies, and thanks for them, that suggested using two > rules. In fact, that's what I did but I was still interested in the question > because I think it is quite reasonable to calculate quantities as part of > the test and have them available for the replacement code. It might not just > be choosing between two alternatives, where we could substitute two rules, > but might involve a complicated calculation as part of the test and we want > the results of the computation in the replacement routine. > > With a little more investigation I have found that Mathematica does provide > a method for doing this. The trick is to put the test after the body of the > replacement Module. There is a note in the Module Help... > > "You can use Module[{vars}, body /; cond] as the right-hand side of a > transformation rule with a condition attached." > > That forces the replacement to be done immediately and the test can return > results that can be extracted. > > Clear[transformf] > transformf[expr_] := > Module[{testQ}, > > testQ[a_, b_, c_] := > Module[{replacea = False, test}, > test = > Which[ > c === a, replacea = True; True, > c === b, replacea = False; True, > True, False]; > {test, replacea}]; > > expr /. (f[a_, b_]c_) :> > Module[{replacea, work}, > > If[replacea, f[a^2, b], f[a, b^2]] /; (work = testQ[a, b, c]; > replacea = Last[work]; First[work])] > ] > > {f[a, b]a, f[a, b]b, f[a, b]c} // transformf > {f[a^2, b], f[a, b^2], c*f[a, b]} > > David Park > djmp at earthlink.net > http://home.earthlink.net/~djmp/ > > > > From: David Park [mailto:djmp at earthlink.net] To: mathgroup at smc.vnet.net > > Dear MathGroup, > > Here is a routine that mimics a more complicated routine I was working on. I > think it has strange behavior. The routine uses a conditional test on the > pattern variables that as a side effect computes a parameter used in the > replacement. When used on a list this doesn't work because Mathematica does > all of the tests first, leaving only the parameter from the last test, and > then does all of the replacements. Not what I want. > > The sample routine looks at expressions of the form f[a,b]c. If c ===a it > returns f[a^2,b]. If c === b it returns f[a,b^2] and otherwise no > replacement is done. I've added two Print statements to clarify what is > happening. > > transformf[expr_] := > Module[{testQ, replacea}, > > testQ[a_, b_, c_] := > Module[{}, > Print["Testing ", f[a, b]c]; > Which[ > c === a, replacea = True; True, > c === b, replacea = False; True, > True, False]]; > > expr /. (f[a_, b_]c_) /; testQ[a, b, c] :> > Module[{}, > Print["Processing " , f[a, b]c]; > If[replacea, f[a^2, b], f[a, b^2]]] > ] > > If I Map this onto the following list it works as expected. > > transformf /@ {f[a, b]a, f[a, b]b} > Testing a f[a, b] > Processing a f[a, b] > Testing b f[a, b] > Processing b f[a, b] > {f[a^2, b], f[a, b^2]} > > However, if I use the routine on the entire list I obtain: > > {f[a, b]a, f[a, b]b} // transformf > Testing a f[a, b] > Testing b f[a, b] > Processing a f[a, b] > Processing b f[a, b] > {f[a, b^2], f[a, b^2]} > > which I regard as incorrect. The Help for ReplaceAll says... > > "ReplaceAll looks at each part of expr, tries all the rules on it, and then > goes on to the next part of expr." > > That seems to me to be a vague and inaccurate statement. One might think > that if the rule matched then the replacement would be done - or at least > calculated. Then ReplaceAll would go on to look at the next part of the > expression. Instead all the tests are done first, and all the matching > replacements are done afterwards. So in the above routine the replacea > parameter is set to the last test result and then used in all of the > replacements. > > That hardly seems fair. Is there a way around this behavior. > > David Park > djmp at earthlink.net > http://home.earthlink.net/~djmp/ > > Everyone should study mathematics - just so they will know what it is to be > wrong. > > > > > > > > > > -- http://chris.chiasson.name/

**Follow-Ups**:**Re: Re: RE: Behavior of ReplaceAll with Computed Results from a Conditional Test***From:*"Chris Chiasson" <chris@chiasson.name>

**References**:**RE: Behavior of ReplaceAll with Computed Results from a Conditional Test***From:*"David Park" <djmp@earthlink.net>