# Tracing my rules

As said in another question, I apply a set of rules to a string (OK, technically written as a function F of several arguments so I can easily apply rules on the fly). Now I want to check whether the correct rule is applied correctly (which can get chaotic). Obviously Trace[expr] does the trick, but the output is not less chaotic, since many rules apply, but most are rejected since they match the pattern, but not an additional /; condition. Ideally MATHEMATICA would show me only rules that didn't fail, the number of the rule (I could introduce it by storing the rule number in the first argument of my function, and then do Trace[expr,F]) and the inbetween values. Some silly artificial working example:

(*rule set*)
F[n_,X___,1,1,Y___]:=F[1,X,2,Y];(*rule 1*)
F[n_,X___,2,3,Y___]:=F[2,X,3,Y]/;Y==4;(*rule 2*)
F[n_,X___,2,3,Y___]:=F[3,X,3,Y]/;Y!=4;(*rule 3*)
(*raw trace: Trace[expr])
{F[0,1,1,3,5],F[1,2,3,5],{{5==4,False},RuleCondition
[$ConditionHold[$ConditionHold[F[2,3,5]]],
False],Fail},{{5!=4,True},
RuleCondition[$ConditionHold[$ConditionHold
[F[3,3,5]]],True],
$ConditionHold[$ConditionHold[F[3,3,5]]]},F[3,3,5]}
(*processed evaluation trace: Trace[expr,F]*)
F[0,1,1,3,5] (*start*)
F[1,2,3,5] (*rule 1 applied successfully*)
F[3,3,5] (*rule 3 applied successfully*)


Note that although this approach already solves my problem, I would prefer a solution without numbering rules, as this must be pattern-matched too and my program is already snailish enough...

(*idea of time-saving output, no n_ in F rules*)
F[1,1,3,5],
F[2,3,5] F[X___,1,1,Y___]->F[X,2,Y]
F[3,5] F[X___,2,3,Y___]->F[X,3,Y],Y!=4


The processing of Trace may be snailish since I just use that for spot-checking correctness.

P.S. Why does letting Y___=Nothing (say input F[0,2,3]) match Y==4 (as the output is F[2,3], not F[3,3])? Is an empty slot equal to anything?

• Re P.S.: Y == 4 is equivalent to Equal[Y1, Y2,..., 4] when Y is a sequence. If it's an empty sequence, it becomes Equal[4], which is True. Commented Aug 26, 2021 at 13:21
• @MichaelE2: D'ooooh! 0=0=0 are two conditions, 0=0 one, and 0 zero, and "no condition needed" must be true. Logical. But surprising if you didn't think it through yet. :-) Commented Aug 27, 2021 at 8:14

## 1 Answer

Perhaps you can do:

Clear[F]
F[X___, 1, 1, Y___] := Echo[Unevaluated @ F[X, 2, Y], "rule 1:"]
F[X___, 2, 3, Y___] := Echo[Unevaluated @ F[X, 3, Y], "rule 2:"] /; Y==4
F[X___, 2, 3, Y___] := Echo[Unevaluated @ F[X, 3, Y], "rule 3:"] /; Y!=4


Then:

F[1, 1, 3, 5]


rule 1: F[2,3,5]

rule 3: F[3,5]

F[3, 5]

• Oops! You are right. Commented Aug 26, 2021 at 23:24
• Needs a bit more rewriting of the rules, but I guess it is much faster. I try it out and report the times here. (A disadvantage may be I need more "postprocessing" for the output - possibly it is better to have two codes anyway, one for checking and one for evaluating.) Commented Aug 27, 2021 at 8:19
• Inbetween comment: Of course, I first defined ec[n_,X_]:=Echo[Unevaluated@X,"rule"<>ToString[n]<>":"] by law of good programming (DON'T! REPEAT! CODE!). You can guess where that ended... :-) Commented Aug 30, 2021 at 9:05