This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author josh.r
Recipients Aaron Hall, brandtbucher, gvanrossum, josh.r, mark.dickinson, rhettinger, scoder, serhiy.storchaka, slam, steve.dower, xtreak
Date 2020-02-27.01:26:36
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1582766797.08.0.136948892225.issue36144@roundup.psfhosted.org>
In-reply-to
Content
Sorry, I think I need examples to grok this in the general case. ChainMap unioned with dict makes sense to me (it's equivalent to update or copy-and-update on the top level dict in the ChainMap). But ChainMap unioned with another ChainMap is less clear. Could you give examples of what the expected end result is for:

    d1 = {'a': 1, 'b': 2}
    d2 = {'b': 3, 'c': 4}
    d3 = {'a': 5, 'd': 6}
    d4 = {'d': 7, 'e': 8}
    cm1 = ChainMap(d1, d2)
    cm2 = ChainMap{d3, d4)

followed by either:

    cm3 = cm1 | cm2

or
    cm1 |= cm2

? As in, what is the precise state of the ChainMap cm3 or the mutated cm1, referencing d1, d2, d3 and d4 when they are still incorporated by references in the chain?

My impression from what you said is that the plan would be for the updated cm1 to preserve references to d1 and d2 only, with the contents of cm2 (d3 and d4) effectively flattened and applied as an in-place update to d1, with an end result equivalent to having done:

    cm1 = ChainMap(d1, d2)
    d1 |= d4
    d1 |= d3

(except the key ordering would actually follow d3 first, and d4 second), while cm3 would effectively be equivalent to having done (note ordering):

    cm3 = ChainMap(d1 | d4 | d3, d2)

though again, key ordering would be based on d1, then d3, then d4, not quite matching the union behavior. And a reference to d2 would be preserved in the final result, but not any other original dict. Is that correct? If so, it seems like it's wasting ChainMap's key feature (lazy accumulation of maps), where:

    cm1 |= cm2

could be equivalent to either:

    cm1.maps += cm2.maps

though that means cm1 wins overlaps, where normal union would have cm2 win, or to hew closer to normal union behavior, make it equivalent to:

    cm1.map[:0] = cm2.maps

prepending all of cm2's maps to have the same duplicate handling rules as regular dicts (right side wins) at the expense of changing which map cm1 uses as the target for writes and deletes. In either case it would hew to the spirit of ChainMap, making dict "union"-ing an essentially free operation, in exchange for increasing the costs of lookups that don't hit the top dict.
History
Date User Action Args
2020-02-27 01:26:37josh.rsetrecipients: + josh.r, gvanrossum, rhettinger, mark.dickinson, scoder, serhiy.storchaka, steve.dower, Aaron Hall, slam, xtreak, brandtbucher
2020-02-27 01:26:37josh.rsetmessageid: <1582766797.08.0.136948892225.issue36144@roundup.psfhosted.org>
2020-02-27 01:26:37josh.rlinkissue36144 messages
2020-02-27 01:26:36josh.rcreate