1
$\begingroup$

I am trying to apply a series of individual rules onto an expression sequentially, but also not have to write out the repeated ReplaceAll functions each time I want to perform the same series of rules.

Here's an illustrative example of my problem:

(* r1, r2 and r3 are the individual rule transformations *)
r1[a_] := {a :> 3 a};
r2[a_] := {a :> -a};
r3[a_] := {a :> a + 1};

(* Try to define a single rule operator which applies rules in a given order *)
rall[a_] := r1[a] /. r2[a] /. r3[a];

(* Ideal answer is given by *)
a /. r1[a] /. r2[a] /. r3[a]

Which evaluates to -3(a+1), applying each rule sequentially, whereas

a /. rall[a]

evaluates to a, having not applied any of the rules. This can be understood, since rall[a] evaluates to {-a-1:>3(-(a+1))}, having applied the rules r2[a] and r3[a] to the initial r1[a] term, not just the rhs instances of a in the rules expressions.

How can I build a composite rule function that achieves my aim? Is there a way to delay the evaluation of the rules stated in rall[a] until I apply it to a variable?

$\endgroup$
  • $\begingroup$ Functions are already based on replacement rules. You could write: r1[a_] := 3a; r2[a_] := -a; r3[a_] := a+1; rall[a_] := r3@r2@r1[a], then try and evaluate rall[a]. $\endgroup$ – MarcoB Jun 17 '15 at 21:51
  • $\begingroup$ Well, obviously the logic of defining rall[a_] as you did it, is flawed. You instruct the second and third rule to act on the first, instead of all rules to act on some expression - and that is what you get. Why not doing something like rall[a_] := Function[expr, expr /. r1[a] /. r2[a] /. r3[a]];, and then rall[a][a]? $\endgroup$ – Leonid Shifrin Jun 17 '15 at 21:51
4
$\begingroup$

Maybe with the help of Fold or FoldList :

See what happens here:

FoldList[#1 /. #2 &, a, {r1[a], r2[a], r3[a]}]

{a, 3 a, -3 a, -3 (1 + a)}

Replace FoldList with Fold to get directly the last result.

In other words:

rall[a_] := Fold[#1 /. #2 &, a, {r1[a], r2[a], r3[a]}]

then

rall[a]

-3 (1 + a)

$\endgroup$
  • $\begingroup$ That's great. How do I extend this to multiple rule arguments, say for r1[a,b]? I tried some variations on syntax such as Fold[{#1,#2}/.#3 &[a,b], {r1[a,b],r2[a,b],r3[a,b]}] but can't seem to find the correct extension. $\endgroup$ – SLesslyTall Jun 18 '15 at 8:49
  • $\begingroup$ @SLesslyTall Simply Fold[#1 /. #2 &, expr[a,b], {r1[a, b], r2[a, b], r3[a, b]}] where expr[a,b] stands for any initial expression you want to replace, for example Sin[a]^b, or any list {a,b,a*b^2,...}, ... $\endgroup$ – SquareOne Jun 18 '15 at 12:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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