Message Boards Message Boards

1
|
5082 Views
|
9 Replies
|
6 Total Likes
View groups...
Share
Share this post:

Rewrite rule for the values of an Association?

Posted 8 years ago

Can someone help me understand why these two are different, please?

Association[a->{b,c,d,e}]/.x_List:>Drop[x,1]

which gives the result

<|a->Drop[{b,c,d,e},1]|>

and

something[a->{b,c,d,e}]/.x_List:>Drop[x,1]

which gives the result

something[a->{c,d,e}]

What is special about Association so that the Drop function is not evaluated?

POSTED BY: Peter Sjogren
9 Replies

I found that Replace (rather than ReplaceAll) does work as expected:

Replace[Association[a -> {1, 2, 3, 4}, b -> 3], x_List :> Drop[x, 1], {1}]

gives:

<|a -> {2, 3, 4}, b -> 3|>

as one would expect...Hope that works for you! But why this works (as opposed to ReplaceAll)? I'm not sure, might be a bug...

POSTED BY: Sander Huisman
Posted 8 years ago

Great find! It seems really odd to me that one works and not the other. I'm going to report this as a bug just to see what they have to say about it. Thanks for your help.

/Peter

POSTED BY: Peter Sjogren

Please share their reply here, it would be informative for more people and useful for future reference...

POSTED BY: Sander Huisman
Posted 8 years ago

Yes, of course I will.

POSTED BY: Peter Sjogren
Posted 8 years ago

Wolfram support acknowledged the bug and passed it to the development team. They also offered this workaround:

<|a->{b,c,d,e,f}|>/.x_List:>RuleCondition[Drop[x,1]]

which is interesting because RuleCondition is an Internal Symbol and I don't know exactly what it does.

POSTED BY: Peter Sjogren

It has to do with Rule (or RuleDelayed) and Condition, it is indeed used internally:

Trace[Cases[{2}, i_ :> i /; OddQ[i]], TraceAbove -> All, TraceInternal -> True]

giving a:

RuleCondition[$ConditionHold[$ConditionHold[2]], False]

somewhere during evaluation. Or the same with True (instead of False) if EvenQ rather than OddQ is used. but what it REALLY does; not so sure!

POSTED BY: Sander Huisman
Posted 8 years ago

Thank you for the answer. I sort of hoped that Attributes[Association] would contain something that explained this. I experience the same behavior in the Wolfram Cloud and in Mathematica Home version 10.3. In the former the attributes are {HoldAllComplete, Protected} and in the latter only {Protected}.

If I understand you correctly Replace should not work inside something that has AtomQ True. (Can you give a reference where I can get this explained?). This should not work then:

Association[a->{b,c,d,e}]/.{x_,y__}->{y}

but it does, and gives the result:

<|a->{c,d,e}|>

Does anyone know how I should think about this?

POSTED BY: Peter Sjogren

In Version 11.0.1 (and 10.4.1) the attributes of Association are:

{HoldAllComplete, Protected}

I think the help of AtomQ has a statement:

AtomQ gives True for any object whose subparts cannot be accessed using functions like Map.

notice that it says like Map. For example one can not change the numerator/denominator of fractions or parts of a complex number:

a = 3/4
a /. 4 -> 5
3/4
3/4

a = 1 + 2 I
a /. 2 -> 3
1+2I
1+2I

Or similarly, parts of a sparse-arrays, so that lead me to believe that ReplaceAll does not touch atoms (subatomic parts) in general.

I just found that in the help of ReplaceAll it says, regarding Associations, that:

Most patterns are only compared against the values of an association.

<|a -> f[b -> c]|> /. (k_ -> v_) :> g[k, v]
<|a -> f[g[b, c]]|>

For compound patterns matching an Association, inner patterns match both keys and values:

<|a -> f[b -> c]|> /. _[k_ -> v_] :> g[k, v]
g[a, f[b -> c]]

By excluding heads matching Association, only comparisons against values are done:

<|a -> f[b -> c]|> /. Except[Association][k_ -> v_] :> g[k, v]
<|a -> g[b, c]|>

So apparently Replace can be used with Associations, though I'm not sure where that leaves us, especially the "Most patterns are only compared against the values" is kind of strange; what is meant by most? How can one determine what is checked... so many questions!

POSTED BY: Sander Huisman

I'm surprised that that even works! Association is kinda weird in some sense; it is an 'atom', AtomQ[Association[...]] will return True, such that Replace and ReplaceAll should not work inside the guts of an association. Something that DOES work is using the following:

assoc = Association[a -> {1, 2, 3, 4}, b -> 3, c -> 5]
KeyValueMap[#1 -> #2 /. x_List :> Drop[x, 1] &, assoc]

Not the most elegant (or fast) though...

also you could do:

Association[Normal[assoc] /. (y_ -> x_List) :> (y -> Drop[x, 1])]

again, not very elegant (nor fast).

I think the reason why Replace(All) should not work, is because it is not clear that it should work on Values or Keys, or both? Functions like Sort or Map are 'blind' to the keys. I'm not sure how Replace(All) regards an association, and I'm also not sure if this is a bug or feature to be honest...

I wish I had a more satisfactory answer to be honest...

POSTED BY: Sander Huisman
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract