4
$\begingroup$

Replacements acting on Associations confuse me. I have read Pattern matching to a function evaluation inside an Association and How to use ReplaceAll and RuleDelayed with an Association? and I understand how to use RuleCondition (or something equivalent) to insert an evaluated expression into the RHS of the held rule.

But this is not the only difficulty with replacement rules acting on Associations. Compare the following

replaceAllIncludingAssociations[expr_, 

replacementRule_] := (expr /. assoc_Association :> assocHolder[Normal[assoc]]) /. replacementRule /. assocHolder -> Association (Here a RuleCondition on the RHS would not have helped.)

Applying a function by Key pattern, preserving Association order could probably be used to find a solution but it would require some adaption and learning a new syntax. I would prefer something that is close to the expected syntax of ReplaceAll.


The following seems to work as I would expect ReplaceAll to work. Of course performance wise it is probably terrible:

    replaceAllIncludingAssociations[expr_,replacementRule_] := (expr //. assoc_Association :> assocHolder[Normal[assoc]]) /.  replacementRule /. assocHolder -> Association
$\endgroup$
6
$\begingroup$

but it would require some adaption and learning a new syntax

I recommend adapting and learning new syntax. Associations are atomic objects and normal structural replacement rules should not work on them.

This fails

In[50]:= Association[{"a" -> 1, "b" -> 2}] /. ("a" -> num_) :> "a" -> 6

Out[50]= <|"a" -> 1, "b" -> 2|>

because "a" -> num_ is not part of the evaluated association

In[47]:= FreeQ[Association[{"a" -> 1, "b" -> 2}], "a" -> num_]

Out[47]= True

This is why KeyValuePattern was introduced. A replacement rule that will take any association that has "a" as a key and set the value equal to 6 could be written

In[51]:= 
Association[{"a" -> 1, "b" -> 2}] /. 
 x : KeyValuePattern["a" -> _] :> Join[x, <|"a" -> 6|>]

Out[51]= <|"a" -> 6, "b" -> 2|>

Your method of converting the association to a normal expression, acting on that expression, and then converting back to an association is guaranteed to work but I think it misses the point of Association.

$\endgroup$
1
  • 1
    $\begingroup$ Thanks! This is much simpler than I thought it would be and definitely satisfies my requirement of a similar syntax to ReplaceAll. $\endgroup$
    – Kvothe
    Sep 28 at 11:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.