
On Mar 4, 2019, at 4:51 AM, Stefan Behnel <stefan_ml@behnel.de> wrote:
I think the main intentions is to close a gap in the language.
[1,2,3] + [4,5,6]
works for lists and tuples,
{1,2,3} | {4,5,6}
works for sets, but joining two dicts isn't simply
{1:2, 3:4} + {5:6}
but requires either some obscure syntax or a statement instead of a simple expression.
The proposal is to enable the obvious syntax for something that should be obvious.
I would challenge that this dictionary merging is something that is obvious. The existing sequences are simple collections of values where a dictionary is a mapping of values. The difference between the two is akin to the difference between a mathematical array or set and a unary mapping function. There is a clear and obvious way to combine arrays and sets -- concatenation for arrays and union for sets. Combining mapping functions is less than obvious. "Putting Metaclasses to Work" (ISBN-13 978-0201433050) presents a more mathematical view of programming language types that includes two distinct operations for combining dictionaries -- merge and recursive merge. For two input dictionaries D1 & D2 and the output dictionary O D1 merge D2 O is D1 with the of those keys of D2 that do not have keys in D1 D1 recursive-merge D2 For all keys k, O[k] = D1[k] recursive merge D2[k] if both D1[k] and D2[k] are dictionaries, otherwise O[k] = (D1 merge D2)[k]. Note that neither of the cases is the same as:
O = D1.copy() O.update(D2)
So that gives us three different ways to combine dictionaries that are each sensible. The following example uses dictionaries from "Putting Metaclasses to Work":
d1 = { ... 'title': 'Structured Programming', ... 'authors': 'Dahl, Dijkstra, and Hoare', ... 'locations': { ... 'Dahl': 'University of Oslo', ... 'Dijkstra': 'University of Texas', ... 'Hoare': 'Oxford University', ... }, ... }
d2 = { ... 'publisher': 'Academic Press', ... 'locations': { ... 'North America': 'New York', ... 'Europe': 'London', ... }, ... }
o = d1.copy() o.update(d2) o {'publisher': 'Academic Press', 'title': 'Structured Programming', 'locations': {'North America': 'New York', 'Europe': 'London'}, 'authors': 'Dahl, Dijkstra, and Hoare'}
merge(d1, d2) {'publisher': 'Academic Press', 'title': 'Structured Programming', 'locations': {'Dijkstra': 'University of Texas', 'Hoare': 'Oxford University', 'Dahl': 'University of Oslo'}, 'authors': 'Dahl, Dijkstra, and Hoare'}
recursive_merge(d1, d2) {'publisher': 'Academic Press', 'title': 'Structured Programming', 'locations': {'North America': 'New York', 'Europe': 'London', 'Dijkstra': 'University of Texas', 'Hoare': 'Oxford University', 'Dahl': 'University of Oslo'}, 'authors': 'Dahl, Dijkstra, and Hoare'}
https://repl.it/@dave_shawley/PuttingMetaclassesToWork <https://repl.it/@dave_shawley/PuttingMetaclassesToWork>
IMO, having more than one obvious outcome means that we should refuse the temptation to guess. If we do, then the result is only obvious to a subset of users and will be a surprise to the others. It's also useful to note that I am having trouble coming up with another programming language that supports a "+" operator for map types. Does anyone have an example of another programming language that allows for addition of dictionaries/mappings? If so, what is the behavior there? - dave -- Any linter or project that treats PEP 8 as mandatory has *already* failed, as PEP 8 itself states that the rules can be broken as needed. - Paul Moore.