2

This behavior of replacement rule seems inconsistent in Association. First, the baseline example works as intended:

{ data[{1, 2, 3}],  data[{3, 4}]} // 
 ReplaceAll[data[x_List] :> Length[x]] 

{3, 2}

But in Association

<|"a" -> {1, 2, 3}, "b" ->  {3, 4}|> //  ReplaceAll[x_List :> Length[x]] 

<|"a" -> Length[{1, 2, 3}], "b" -> Length[{3, 4}]|>

No problem with Map:

<|"a" -> data[{1, 2, 3}], "b" ->  data[{3, 4}]|> // ReplaceAll[data[x_List] :> x]  // Map[Length]

<|"a" -> 3, "b" -> 2|>

Is this behavior by design or a bug?

Note, as per comment by Simon Woods, explicit Evaluate on the right hand side of RuleDelayed has precedence over the replacement so can't be used as a workaround in ReplaceAll - however, it works externally:

<|"a" -> {1, 2, 3}, "b" ->  {3, 4}|> // 
  ReplaceAll[x_List :> Length[x]] // Map[Evaluate]

<|"a" -> 3, "b" -> 2|>

EDIT:

Following comments, and in Questions here and here and from WR support, HoldAllComplete causes this behavior.

Wouldn't it more appropriate if only the Keys were held? Keys are supposed to be treated Verbatim, not as patterns to be matched. But Values are intended to be transparent.

The current model introduces an inefficiency for deeply nested Associations: the need to (post)-Map Evaluate to Infinity to achieve the desired replacement.

Would appreciate feedback on this issue, and perhaps make the case to WR.

alancalvitti
  • 15,143
  • 3
  • 27
  • 92
  • When you put Evaluate@Length[x] on the RHS of RuleDelayed it evaluates before the pattern is matched, so x has no value. Hence Length[x]=0 and Head[x]=Symbol – Simon Woods Jan 09 '17 at 19:36
  • @SimonWoods, thanks, wasn't aware of that precedence rule. However, what about the underlying issue? – alancalvitti Jan 09 '17 at 19:41
  • I don't know about the first issue, it came as a surprise to me too. But I think the question would be better without the second half which is a straightforward misunderstanding about what Evaluate does. – Simon Woods Jan 09 '17 at 19:46
  • @SimonWoods, sounds good, will delete the second part & attribute you. – alancalvitti Jan 09 '17 at 19:51
  • I think this is related. – Simon Woods Jan 09 '17 at 19:53
  • But isn't this the answer? 124603 – Kuba Jan 09 '17 at 20:05
  • 3
  • 1
    @Kuba But it looks like various pieces of the full explanation has been scattered in all those questions we link here, while it would be nice to have a single larger canonical discussion of this and strongly related matters. – Leonid Shifrin Jan 09 '17 at 20:13
  • @LeonidShifrin, an all, I edited the Q adding the link and comments. Would appreciate if you took another look Re not holding Keys. – alancalvitti Jan 11 '17 at 19:08
  • @SimonWoods, please see comment to Leonid above. – alancalvitti Jan 11 '17 at 19:08
  • @Kuba, please see above two comments. – alancalvitti Jan 11 '17 at 19:08
  • @alancalvitti I don't see a point in discussing that design decision (HoldAllComplete for assocs), since whatever we decide, I do know for sure that this won't be changed. There are also good technical reasons for why assocs were made HoldAllComplete. On the practical side, the way out was suggested in a number of answers including mine in the linked question - use Trott - Strzebonski trick (RuleCondition is the shortest form of it), like ReplaceAll[x_List :> RuleCondition @ Length[x]] instead of ReplaceAll[x_List :> Length[x]] in your example. – Leonid Shifrin Jan 11 '17 at 19:33
  • @LeonidShifrin, just b/c it might not be changed for sure doesn't mean it can't be changed if there's a better way. I identified a practical limitation. Also, we might not have control over data stored as Rule versus RuleDelayed. – alancalvitti Jan 11 '17 at 22:06
  • 1
    @LeonidShifrin, ps, WR support has filed a suggestion with devs on this issue - similar to what I wrote up in the EDIT - not that this means it will be handled, they're usually backlogged. – alancalvitti Jan 11 '17 at 22:08

0 Answers0