[Python-ideas] PEP: Dict addition and subtraction

Inada Naoki songofacandy at gmail.com
Wed Mar 6 04:26:06 EST 2019


On Wed, Mar 6, 2019 at 5:34 PM Stefan Behnel <stefan_ml at behnel.de> wrote:
>
> INADA Naoki schrieb am 05.03.19 um 08:03:> On Tue, Mar 5, 2019 at 12:02 AM
> Stefan Behnel wrote:
> >> INADA Naoki schrieb am 04.03.19 um 11:15:
> >>> Why statement is not enough?
> >>
> >> I'm not sure I understand why you're asking this, but a statement is
> >> "not enough" because it's a statement and not an expression. It does
> >> not replace the convenience of an expression.
> >
> > It seems tautology and say nothing.
>
> That's close to what I thought when I read your question. :)
>
>
> > What is "convenience of an expression"?
>
> It's the convenience of being able to write an expression that generates
> the thing you need, rather than having to split code into statements that
> create it step by step before you can use it.
>

I don't think it's reasonable rationale for adding operator.

First, Python sometimes force people to use statement intentionally.

Strictly speaking, dict.update() is an expression.  But it not return `self`
so you must split statements.  It's design decision.

So "add operator because I want expression" is bad reasoning to me.
If it is valid reasoning, every mutating method should have operator.
It's crazy idea.

Second, operator is not required for expression.  And adding operator
must have high bar than adding method because it introduces more
complexity and it could seen cryptic especially when the operator doesn't
have good math metaphor.

So I proposed adding dict.merge() instead of adding dict + as a counter
proposal.

If "I want expression" is really main motivation, it must be enough.


> Think of comprehensions versus for-loops. Comprehensions are expressions
> that don't add anything to the language that a for-loop cannot achieve.
> Still, everyone uses them because they are extremely convenient.
>

I agree that comprehension is extremely convenient.
But I think the main reason is it is compact and readable.
If comprehension is not compact and readable as for-loop, it's not extremely
convenient.

>
> > Is it needed to make Python more readable language?
>
> No, just like comprehensions, it's not "needed". It's just convenient.
>

I think comprehension is needed to make Python more readable language,
not just for convenient.

>
> > Anyway, If "there is expression" is the main reason for this proposal,
> > symbolic operator is not necessary.
>
> As said, "needed" is not the right word.

Maybe, I misunderstood nuance of the word "needed".  English and Japanese
are very different language.  sorry.

> Being able to use a decorator
> closes a gap in the language. Just like list comprehensions fit generator
> expressions and vice versa. There is no "need" for being able to write
>
>     [x**2 for x in seq]
>     {x**2 for x in seq}
>
> when you can equally well write
>
>     list(x**2 for x in seq)
>     set(x**2 for x in seq)
>
> But I certainly wouldn't complain about that redundancy in the language.
>

OK, I must agree this point. [] and {} has good metaphor in math.
We use [1, 2, 3,... ] for series, and {1, 2, 3, ...} for sets.

>
> > `new = d1.updated(d2)` or `new = dict.merge(d1, d2)` are enough. Python
> > preferred name over symbol in general. Symbols are readable and
> > understandable only when it has good math metaphor.
> >
> > Sets has symbol operator because it is well known in set in math, not
> > because set is frequently used.
> >
> > In case of dict, there is no simple metaphor in math.
>
> So then, if "list+list" and "tuple+tuple" wasn't available through an
> operator, would you also reject the idea of adding it, argueing that we
> could use this:
>
>     L = L1.extended(L2)
>
> I honestly do not see the math relation in concatenation via "+".
>

First of all, concatenating sequence (especially str) is extremely
frequent than merging dict.  My point is dict + dict is major abuse
of + than seq + seq and it's usage is smaller than seq + seq.

Let's describe why I think dict+dict is "major" abuse.

As I said before, it's common to assign operator for concatenation in
regular language, while middle-dot is used common.

When the commonly-used operator is not in ASCII, other symbol can
be used as alternative.  We used | instead of ∪.

In case of dict, it's not common to assign operator for merging in math,
as far as I know.

(Maybe, "direct sum" ⊕ is similar to it.  But it doesn't allow intersection.
So ValueError must be raised for duplicated key if we use "direct sum"
for metaphor.
But direct sum is higher-level math than "union" of set.  I don't think
it's good idea to use it as metaphor.)

That's one of reasons I think seq + seq is "little" abuse and dict +
dict is "major" abuse.

Another reason is "throw some values away" doesn't fit mental model of "sum",
as I said already in earlier mail.


> But, given that "+" and "|" already have the meaning of "merging two
> containers into one" in Python, I think it makes sense to allow that also
> for dicts.
>

+ is used for concatenate, it is more strict than just merge.

If + is allowed for dict, set should support it too for consistency.
Then, meaning of "+ for container" become "sum up two containers in
some way, defined by the container type."  It's consistent.

Kotlin uses + for this meaning.  Scala uses ++ for this meaning.

But this is a large design change of the language.  Is this really required?
I feel adding a method is enough.

-- 
Inada Naoki  <songofacandy at gmail.com>


More information about the Python-ideas mailing list