(This seems to be a very basic necessity in a language having pattern-matching capabilities such as Mathematica, yet I struggled for many hours to find a common solution to this problem.)
Suppose there is a pattern with some of its sub-elements named, and there is an expression that matches it. How do I generate a list of replacement rules that maps sub-element names into their values in the matching expression? E.g.,
patt=f_[_, s_, x___];
expr=ab[c, d, e, f];
mkMatchRules[expr,patt]
>> {f -> ab, s -> d, x -> Sequence[e, f]}
I have written a solution to this,
collectAllPattVars[patt_] := Union[Map[Part[#, 1] &,
Cases[patt, _Pattern, {0, Infinity}, Heads -> True]]];
mkMatchRules[expr_, patt_] := Module[
{pattVars = collectAllPattVars[patt], mkRhs},
mkRhs = Block[{$}, ReleaseHold[Hold[patt :> $] /. $ -> With[{$ = Map[List, pattVars]}, $]]];
If[MatchQ[expr, patt],
MapThread[Rule[#1, If[Length[#2] == 1, #2[[1]], Sequence @@ #2]] &,
{pattVars, Replace[expr, mkRhs]}],
$Failed]];
which produces the result in the example above However, I hope somebody knows a more elegant way to do this.
Comments
Post a Comment