6
$\begingroup$

Is the last of these results expected? If so, how?

assoc=<|"a"->1,"b"->2|>;
assoc["a"]+=1;
assoc (* <|"a" -> 2, "b" -> 2|> *)
assoc[[{"a","b"}]]=1;
assoc  (* <|"a" -> 1, "b" -> 1|> *)
assoc[[{"a","b"}]]+=1;
assoc  (* <|"a" -> <|"a" -> 2, "b" -> 2|>, "b" -> <|"a" -> 2, "b" -> 2|>|> *)

Edit:

Kuba helpfully points out that this reflects the behavior of Part, specifically

assoc = <|"a" -> 1, "b" -> 2|>;
assoc[[{"a", "b"}]]  (* <|"a" -> 1, "b" -> 2|> *)

Unfortunately, this pushes my question back to the behavior of Part. We are told by the docs that Part[expr,i] gives the ith part of expr and that Part[expr,{i1,i2,…}] gives a list of the parts i1, i2, … of expr. This seems to imply that

Part[expr, {i1,i2,...}]==(Part[expr,#]&/@{i1,i2,...})

But this is clearly not the case for associations. E.g.,

assoc[[#]] & /@ {"a", "b"}     (* {1,2} *)

How am I misreading the docs?

$\endgroup$
3
  • $\begingroup$ Part is given special instructions for some atomic objects, like sparse arrays and associations, but they don't directly return the specified parts of the underlying data structure. It was apparently decided that the benefit of this behavior outweighed the inconsistency it introduces. $\endgroup$
    – Jason B.
    Commented Nov 17, 2018 at 20:02
  • $\begingroup$ About the edit, take a look at ref / Part / Generalizations and Extensions examples. That is expected but yes, wording could be improved. Feel free to ask WRI support. $\endgroup$
    – Kuba
    Commented Nov 17, 2018 at 21:25
  • $\begingroup$ @Kuba Oh, I see what you mean. Even after your pointing me to it for rereading, I find that wording very far from clear! Thanks! $\endgroup$
    – Alan
    Commented Nov 17, 2018 at 22:35

1 Answer 1

5
$\begingroup$

Maybe not at the first sight but it is expected once you think more about this.

 assoc[[{"a", "b"}]] +=1

is

assoc[[{"a", "b"}]] = (assoc[[{"a", "b"}]] + 1 )

and while rhs operation is still ok, the following one is not defined for associations (not counting generic assignment to values):

assoc[[{"a", "b"}]] = <|"a" -> 2, "b" ->3|>

in case of Lists only dimensions play a role for threading but here keys too. There are Merge and friends for this kind of operations and by default it will just treat it as a single element rhs case, assigning association to each value.

Trace also makes sense:

assoc[[{"a", "b"}]] += 1; // Trace
{ assoc[[{a,b}]]+=1;
, { assoc[[{a,b}]]+=1
, { { assoc
    , <|a->1,b->2|>
    }
  , <|a->1,b->2|>[[{a,b}]]
  , <|a->1,b->2|>
  }
, { assoc[[{a,b}]]=<|a->2,b->3|>
  , <|a->2,b->3|>
  }
, <|a->2,b->3|>
}
, Null
}
$\endgroup$
1
  • $\begingroup$ I've elaborated my question in response to your comment. (See the edit.) $\endgroup$
    – Alan
    Commented Nov 17, 2018 at 19:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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