If we use this "literally concat" metaphor, I still think set should have `+` as alias to `|` for consistency.

I agree.

I think "|" keeps commutativity only because it's minor than `+`.

I suppose that's true, fair point.

I guess I would be ok with | no longer always implying commutativity if we were repurposing it for some radically different purpose. But dicts and sets are similar enough that I think having them both use similar but ultimately different definitions of "|" is going to have non-zero cost, especially when reading or modifying future code that makes heavy use of both data structures.

Maybe that cost is worth it. I'm personally not convinced, but I do think it should be taken into account..

Hmm.  The PEP proposed dict - dict, which is similar to set - set (difference).

Now that you point it out, I think I also dislike `d1 - d2` for the same reasons I listed earlier: it's not consistent with set semantics. One other objection I overlooked is that the PEP currently requires both operands to be dicts when doing "d1 - d2" . So doing {"a": 1, "b": 2, "c": 3} - ["a", "b"] is currently disallowed (though doing d1 -= ["a", "b"] is apparently ok).

I can sympathize: allowing "d1 - some_iter" feels a little too magical to me. But it's unfortunately restrictive -- I suspect removing keys stored within a list or something would be just as common of a use-case if not more so then removing keys stored in another dict.

I propose that we instead add methods like "d1.without_keys(...)" and "d1.remove_keys(...)" that can accept any iterable of keys. These two methods would replace "d1.__sub__(...)" and "d1.__isub__(...)" respectively. The exact method names and semantics could probably do with a little more bikeshedding, but I think this idea would remove a false symmetry between "d1 + d2" and "d1 - d2" that doesn't actually really exist while being more broadly useful.

Or I guess we could just remove that restriction: "it feels too magical" isn't a great objection on my part. Either way, that part of the PEP could use some more refinement, I think.

-- Michael

On Wed, Mar 6, 2019 at 8:29 AM Inada Naoki <songofacandy@gmail.com> wrote:
On Wed, Mar 6, 2019 at 10:59 PM Michael Lee <michael.lee.0x2a@gmail.com> wrote:

> I think the behavior proposed in the PEP makes sense whether you think of "+" as meaning "concatenation" or "merging".
> If your instinct is to assume "+" means "concatenation", then it would be natural to assume that {"a": 1, "b": 2} + {"c": 3, "b": 4} would be identical to {"a": 1, "b": 2, "c": 3, "b": 4} -- literally concat the key-value pairs into a new dict.

Nice explanation.  You reduced my opposite to `+` by "literally concat".
Better example, {"a": 1, "b": 2} + {"c": 4, "b": 3} == {"a": 1, "b":
2, "c": 4, "b": 3} == {"a": 1, "b": 3, "c": 4}

On the other hand, union of set is also "literally concat".  If we use
this "literally concat" metaphor,
I still think set should have `+` as alias to `|` for consistency.

> Using "|" would also violate an important existing property of unions: the invariant "d1 | d2 == d2 | d1" is no longer true. As far as I'm aware, the union operation is always taken to be commutative in math, and so I think it's important that we preserve that property in Python. At the very least, I think it's far more important to preserve commutativity of unions then it is to preserve some of the invariants I've seen proposed above, like "len(d1 + d2) == len(d1) + len(d2)".

I think both rule are "rather a coincidence than a conscious decision".

I think "|" keeps commutativity only because it's minor than `+`.  Easy operator
is abused easily more than minor operator.

And I think every "coincidence" rules are important.  They makes
understanding Python easy.
Every people "discover" rules and consistency while learning language.

This is a matter of balance.  There are no right answer.  Someone
*feel* rule A is important than B.
Someone feel opposite.

> But I do know that I'm a strong -1 on adding set operations to dicts: it's not possible to preserve the existing semantics of union (and intersection) with dict and  think expressions like "d1 | d2" and "d1 & d2" would just be confusing and misleading to encounter in the wild.

Hmm.  The PEP proposed dict - dict, which is similar to set - set (difference).
To me, {"a": 1, "b": 2} - {"b": 3} = {"a": 1} is confusing than {"a":
1, "b": 2} - {"b"} = {"a": 1}.

So I think borrow some semantics from set is good idea.
Both of `dict - set` and `dict & set` makes sense to me.

* `dict - set` can be used to remove private keys by "blacklist".
* `dict & set` can be used to choose public keys by "whiltelist".

Inada Naoki  <songofacandy@gmail.com>