2
$\begingroup$

This question is a partial followup to my previous question.

Mainly, after using With to inject the proper argument in the function at the rhs of RuleDelayed, it felt appropriate to divide functionality into different contexts/packages.

Namely, package A.wl (see below) contains the core functionality while package B.wl (and possibly subsequent packages C.wl, D.wl etc) contains the patterns to match against (a different set of patterns could be encapsulated in a different package).

When I evaluate the following code segment (from a notebook)

Needs["B`", FileNameJoin[{NotebookDirectory[], "B.wl"}]]

expression = head1["a", 9.8] head1["a", 
  head2["b", 12, 0.7] head3["c", 3], 0] head3["b", 5.9, -3] 
    head1["a", head2["b", -9, 0.5] head3["c", 11], 0.8];

h[expression]

function h returns

{{<|"x1" -> B`Private`x1|>}, 
    {<|"x2" -> B`Private`x2, "y2" -> B`Private`y2|>, 
     <|"x2" -> B`Private`x2, "y2" -> B`Private`y2|>}, {}}

It seems that f fails to provide a match.

After a lot of guesswork I managed to make the code work by noticing that the symbols needed to become matched over the pattern should have a $ appended to their name.

In order to make the code work and obtain the following result, please comment out the second With in function f in package A.

{{<|"x1" -> 9.8|>}, {<|"x2" -> 12, "y2" -> 0.7|>, 
     <|"x2" -> -9, "y2" -> 0.5|>}, {}}

So, my question is, what exactly is going on with what seems to be the renaming of the patterned symbols. Have I missed something or is there a problem with passing patterns between packages?


Code

Copy and paste the code of each package into a .wl file and save both files in a suitable folder, preferably in the same place where the notebook you're using to evaluate the code in the question body is located

Package A

BeginPackage["A`"]

  f::usage = "f";

Begin["`Private`"]

  g[tags_, values_] := Module[{op = Apply[Join]},

  If[
    (* if nothing is matched... *)
    values === {},

    (* ... return {}*)
    {}, 

    (* ... otherwise, return an association of tag-value pairs *)
    MapThread[AssociationThread[#1 -> #2]&, {tags, values}] // op
   ]
  ]

f[expression_, template_] := Module[{symbols},

  (* parts making up a template *)
  symbols = Cases[template, pattn_Pattern :> pattn[[1]], Infinity];

  (* !!! 
  With[{tags = SymbolName /@ symbols, syms = ToExpression[StringJoin[ToString[#], "$"]]& /@ symbols}, *)
  With[{tags = SymbolName /@ symbols, syms = symbols}, 

    Cases[expression, template :> g[tags, syms], Infinity]

   ]
 ]

End[]

EndPackage[]

Package B

BeginPackage["B`"]

  h::usage = "";

Begin["`Private`"]

  Needs["A`", FileNameJoin[{FileNameDrop[$InputFileName, -1], StringJoin["A.wl"]}]]

  templates = {Global`head1["a", x1_], Global`head2["b", x2_, y2_], Global`head3["c", Global`junk[z3_]]};

  h[expression_] := Module[{},

    f[expression, #]& /@ templates

   ]

End[]

EndPackage[]
$\endgroup$
1
  • 1
    $\begingroup$ This is the problem: 20766 and the solution is RuleDelayed @@ Hold[template, g[tags, syms] ]. $\endgroup$ – Kuba Nov 27 '19 at 14:33