Fairly often I find use for replacement rules that call themselves on the right-hand side of the rule, e.g.:
rule = {p___, a, b, c, q___} :> Join[{p, "abc"}, {q} /. rule];
Unfortunately this makes the rule dependent on the specific definition of the Symbol rule
; it can no longer be copied and modified as an independent expression. Ideally I would like to use the #0
syntax for Function
to call the replacement but the most direct application does not work:
# /. {p___, a, b, c, q___} :> Join[{p, "abc"}, #0 @ {q}] & @ "x"
RuleDelayed::rhs: Pattern p___ appears on the right-hand side of rule {p___,a,b,c,q___}:>Join[{p,abc},(#1/. {p___,a,b,c,q___}:>Join[{p,abc},#0[{<<1>>}]]&)[{q}]]. >>
Due to the specific mechanism of #0
its substitution cannot be delayed using e.g. Slot @@ {0}
; the substitution will never occur.
The only pseudo-solution I have found is to move #0
out of the RHS of the rule, then substitute it using another replacement:
# /. {p___, a, b, c, q___} :> "Join"[{p, "abc"}, "#0" @ {q}] /. {"Join" -> Join, "#0" -> #0} & @
{1, 2, a, b, c, 3, {4, a, b, c}, 5}
{1, 2, "abc", 3, {4, "abc"}, 5}
However this destroys the purpose of my construct which was to avoid repeatedly scanning from the beginning of the expression. (There are other uses for self-referential replacement but I believe they are all seriously degraded by this "solution.") It is also fragile to use replacement of "Join"
and "#0"
so additional complexity or dependency would be required.
Is there some other way I can shield the replacement rule (substituted for #0
) from itself without changing the replacement traversal of the expression?
Is there an approach not involving #0
to accomplish my goal?