I have a little example that exhibits a successful pattern match in ReplaceAll
that Cases
misses and I wonder if the assembled sages would be so kind as to offer me an explanation?
This is chopped from an original Prolog emulator by Renan Cabrera circa 2000.
ClearAll[k,s,l,m,j,f,w,g,a,b]
Consider an unordered sequence of statements s
stored in a knowledge base k
, each being a predicate l
about some terms m
, f
, j
, and w
:
k=s[l[m,f],
l[m,w],
l[j,w],
l[j,m]
];
We wish to search this knowledge base for any predicates such that l[m,X_]
and l[j,X_]
, where X_
matches the same term in both predicates. Our first cut is something like
k /. s[l[m,X_],l[j,X_]] -> a[X]
(* Out[42]:= s[l[m,f],l[m,w],l[j,w],l[j,m]] *)
but this doesn't work until we make s flat and orderless (associative and commutative):
SetAttributes[s,{Flat,Orderless}]
and now
k /. s[l[m,X_],l[j,X_]] -> a[X]
(* Out[43]:= s[a[w],l[j,m],l[m,f]] *)
This is, of course, just the same as ReplaceAll[k, s[l[m,X_],l[j,X_]] -> a[X]]
.
(notice the canonical reordering in the output), and now I can extract my answer with something like
Cases[k /. s[ l[m, X_], l[j, X_] ]->a[X],a[Y_]->Y]
(* Out[44]:= {w} *)
The surprise and the question is why doesn't this work?
Cases[k, s[ l[m, X_], l[j, X_] ] -> a[X]]
(* Out[45]:= {} *)
or even this
MatchQ[k, s[ l[m, X_], l[j, X_] ]]
(* Out[46]:= False *)
It's as though ReplaceAll
, Cases
, and MatchQ
are using different pattern matchers.
Will be grateful for advice, clues, discussion, etc.
Cases
orMatchQ
butReplaceAll
. The only hint that I can find is that "ReplaceAll looks at each part of expr, tries all the rules on it, and then goes on to the next part of expr. The first rule that applies to a particular part is used; no further rules are tried on that part, or on any of its subparts." My guess is that this translates into somehow looking at all combinations ofs
with two arguments (due toFlat
), one of them matches and is replaced bya
and the whole thing is returned. $\endgroup$Cases
simply does not take into accountFlat
andOrderless
. It just looks at the elements of the input expression one by one, unlikeReplaceAll
which does considerFlat
andOrderless
too. I realize this doesn't explain what happens, it merely re-states it. $\endgroup$Cases[Hold[3 + 4 + 5], X___ + 4 :> X]
. You could make an answer out of that, I think. $\endgroup$ReplaceAll
(or perhaps of those built-ins that don't search depth-first if there's any other). The title should probably be changed toReplaceAll
. TrySetAttributes[f, Flat];replace=Replace[#1, #2, {0, Infinity}]&;Through@{replace, ReplaceAll}[f[1, 2, 3], f[2, 3]:>8]
. Can't test thoroughly right now $\endgroup$