I'm trying to create a function that builds a replacement rule from a given pattern and I have trouble understanding what's going wrong.
After having written most of the question, I see that it got quite long... For those who want to read the questions first, they're at the bottom. I have also come up with a workaround and possible explanation (I'll post a partial answer to this shortly), but I would still like to understand the issue at hand better.
The goal
For this example, the goal is as follows: Given a patten x_
, output x_ :> <|1 -> x|>
(should work also for y_
, etc.)
My approach
This here does the job just fine:
r1 = x_ /. p : Verbatim[Pattern][a_, _] :> p :> <|1 -> a|>
(* x_ :> Association[1 -> x] *)
Since I need it for later, let's Evaluate
the r.h.s of the pattern:
r2 = x_ /. p : Verbatim[Pattern][a_, _] :> p :> Evaluate@<|1 -> a|>
(* x_ :> <|1 -> x|> *)
Notice the change from Association[...]
to <|...|>
.
The issue
Let's try out those rules on a simple example:
y /. r1
(* <|1 -> y|> *)
y /. r2
(* <|1 -> x|> *)
My attempts at an explanation
It seems something went wrong in the second case. Let's try to see how the two outputs differ:
e1 = Block[
{$ContextPath = {"test`"}, $Context = "test`"},
ToString@FullForm@(x_ /. p : Verbatim[Pattern][a_, _] :> p :> <|1 -> a|>)
]
(* "System`RuleDelayed[System`Pattern[Global`x, System`Blank[]], System`Association[System`Rule[1, Global`x]]]" *)
e2 = Block[
{$ContextPath = {"test`"}, $Context = "test`"},
ToString@FullForm@(x_ /. p : Verbatim[Pattern][a_, _] :> p :> Evaluate@<|1 -> a|>)
]
(* "System`RuleDelayed[System`Pattern[Global`x, System`Blank[]], System`Association[System`Rule[1, Global`x]]]" *)
e1 == e2
(* True *)
r1 === r2
(* False *)
So, apparently, all symbols belong to the same contexts in both rules, but they're still somehow different. Another strange thing:
r2
r3 = x_ :> <|1 -> x|> (* using the output from the line above and prepending 'r3 = ' *)
(* x_ :> Association[1 -> x] *)
f /. r3
(* <|1 -> f|> *)
So simply reentering the output is enough to get it working.
The questions
- What about
Association
is so special that the second approach fails? (As far as I can tell, it's at least not a scoping construct) - How do I prevent this issue?
- For the future, how can I debug an issue like this? (i.e. how do I find out what's different between
r1
andr2
)