4
$\begingroup$

Evaluating <|"key" -> {<|"key" -> "val"|>}|> /. {<|stuff__|>} :> <|stuff|>

Produces <|"key" -> Association["key" -> "val"]|>

Why is Association showing its Head there? If I use Rule instead of RuleDelayed its the same. How do I make the Association[key->val] resolve?

Since I wasn't clear in my original title and question, I'm also looking to a solution to this. The mechanism appears to be the same or similar to that described in Evaluated vs. unevaluated Association but, as with my original title to this question was, those discussion are much more focused on explaining the reasoning.

Domen's answer to this question Associations in replacement rules variable seems to me to suggest that using Rule vs RuleDelayed might help, as it does in the answer there, but that is not true for my case.

$\endgroup$
5
  • 1
    $\begingroup$ This question is similar to: Associations in replacement rules variable. If you believe it’s different, please edit the question, make it clear how it’s different and/or how the answers on that question are not helpful for your problem. $\endgroup$ Commented Aug 23 at 10:46
  • $\begingroup$ @Domen It's not the same question though.. I'm not even sure how that addresses my question. my question is about the display of the association. The actual content of the output is correct, my replacement rule worked, it just doesn't display right $\endgroup$ Commented Aug 23 at 10:55
  • $\begingroup$ I suggest you read through that question and answers (including linked questions in the comments by @WReach). You will see that the problem is not about the display, but about the actual evaluation. $\endgroup$ Commented Aug 23 at 10:57
  • $\begingroup$ I have read through them. I'm now reading through those linked by WReach, and was so when i left my previous comment. Those are much closer in similarity than the one you proposed, which is why its taking me a bit since i read the entire link you provided first before getting to the more on topic ones I'm vaguely seeing a similar connection about evaluation, but it's not clear, and I genuinely think that this question is different enough in spirit and presentation to warrant it's own answer. $\endgroup$ Commented Aug 23 at 11:08
  • 1
    $\begingroup$ IMO, it's a different evaluation issue than in the proposed duplicate. In the duplicate, it prevented the intended replacement. Here the intended replacement works. $\endgroup$ Commented Aug 23 at 14:27

3 Answers 3

5
$\begingroup$

I think the more natural way to achieve what you want is using a pattern for head:

<|"key" -> {<|"key" -> "val"|>}|> /. {a_Association} :> a (* <|"key" -> <|"key" -> "val"|>|> *) 

Alternatively, the solution is the same as in the linked question above, namely use Unevaluated:

<|"key" -> {<|"key" -> "val"|>}|> /. {Unevaluated@<|stuff__|>} :> <|stuff|> (* <|"key" -> {<|"key" -> "val"|>}|> *) 
$\endgroup$
3
  • $\begingroup$ I am like 99% sure i tried using the head pattern and it didn't work!!! but now it does GAAHH.. I must have instead done something slightly different. $\endgroup$ Commented Aug 23 at 12:26
  • $\begingroup$ The second method did not strip the list braces. $\endgroup$ Commented Aug 23 at 13:56
  • $\begingroup$ @Tapiocaweasel, please unaccept my answer and accept another one, because I was not careful enough to see that the Unevaluted trick does not actually work >_<. $\endgroup$ Commented Aug 26 at 9:53
7
$\begingroup$

For some reason I'll never understand, Association holds its arguments, so you have to use the old trick to replace a variable inside a held expression:

In[63]:= <|"key" -> {<|"key" -> "val"|>}|> /. {<|stuff__|>} :> With[{res = <|stuff|>}, res /; True] Out[63]= <|"key" -> <|"key" -> "val"|>|> 
$\endgroup$
4
$\begingroup$

More alternatives that accomplish the desired output:

<|"key" -> {<|"key" -> "val"|>}|> /. {<|stuff__|>} :> <|stuff|> /. <|stuff__|> :> <|stuff|> (* magic! *) <|"key" -> {<|"key" -> "val"|>}|> /. {v : KeyValuePattern[stuff_]} :> v (*or simply: KeyValuePattern[{}] *) <|"key" -> {<|"key" -> "val"|>}|> /. {v_} :> v Replace[{<|stuff__|>} :> <|stuff|>] /@ <|"key" -> {<|"key" -> "val"|>}|> (*or: ReplaceAll *) First /@ <|"key" -> {<|"key" -> "val"|>}|> 

It's not really clear if there is a problem to be solved or merely a "Why?" to be answered. As @Jason points out, Association[] holds its data, and the unevaluated code <|stuff|> that is injected into the outer Association never evaluates to a validated Association. A sign of this is that the output form is Association[...], not <|...|>. MakeBoxes[] formats certain unvalidated expressions differently than their validated forms (Association, InterpolatingFunction, SparseArray, etc.). See Evaluated vs. unevaluated Association.

On the other hand, some operations on associations are overloaded, and sometimes things get evaluated. For instance, the OP's ReplaceAll did not result in the replacement code <|stuff|> being evaluated, but Map-ping ReplaceAll does result in it being evaluated.

However it's done, if a value in an association is to be replaced by a newly constructed association, the replacement needs to be evaluated before it replaces the value.

The last example is the proper way to obtain the example output, imo, but perhaps the OP has more complicated tasks in mind for stuff__.

$\endgroup$
2
  • $\begingroup$ Also RuleCondition i think? $\endgroup$ Commented Aug 24 at 9:25
  • $\begingroup$ @Tapiocaweasel Jason showed that, right? $\endgroup$ Commented Aug 24 at 11:18

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.