On 2020-04-16 2:42 p.m., Andrew Barnert wrote:
On Apr 16, 2020, at 07:19, Soni L. firstname.lastname@example.org wrote:
what about a dict.setdefaults (note the s) that takes in an iterable or a dict, and uses insert-or-ignore behaviour? (unfortunately a lot of iterables and all generators are hashable, and we can't break that.)
I could really use something like that tbh.
Then tell us the use cases that you have in mind.
I can think of lots of common uses for “override this dict with that one”, such as the typical “defaults, config file, environment, argv” thing that most command line tools do. But I can already write that, in idiomatic and readable code (and in fact with variations—update, |, or ChainMap); why would I want to be able to write the same thing in another way that’s conceptually backward, probably less efficient, and doesn’t work in Python 3.8? If the issue is just that you have those default values in a list of pairs rather than a dict, it’s trivial to just construct a dict from that.
Maybe there are good use cases where the usual way would feel backward or wrong and setdefaults would be nicer. But if so, you need to show some.
And they have to be pretty common. You can obviously already write that as `for k, v in defaults: d.setdefault(k, v)`, which is acceptable if it comes up once a year, but demands improvement if people are (or should be, if they only realized it) writing it all over the place.
(If the API were obviously symmetrical, the bar might be a lot lower. See the Haskell dict update operators—I’ll bet I’ve often used the “backward” ones and not even realized it, because they don’t look backward or unusual, and because Haskell in general encourages that kind of symmetrical thinking everywhere, to the extent that even “pass this arg to that function” is almost as commonplace as “call this function with that arg”. But I don’t think Python could get there from here, even if it were a good idea.)
More generally, it seems like you think Python needs to include everything anyone can think of that might theoretically be useful somewhere. But it’s designed to only include (almost) everything people need regularly and can’t just trivially and build for themselves, because aiming for that sweet spot keeps Python discoverable and Python code readable—and similarly for Rust, Swift, Ruby, and other languages that attempt to go that way, even if none of them (including Python) pulls it off perfectly. A kitchen sink language is even worse than a no-batteries-included language—it isn’t just harder to design and implement, it’s harder to use. You have more docs to wade through to find anything, more subtle distinctions to think through to decide, more stuff to remember when you come back to the language after time spent doing other stuff, more trouble reading code written by other people who internalized a different subset of the kitchen sink, etc.
I prefer putting things in order of priority in my ConfigManagers and RepoListManagers and whatnot. mainly because in the RepoListManager, I keep the ConfigManager as the first thing in the list. wouldn't be fun if I had to keep it last, as I need to modify that list regularly.
I also just concatenate the iterators of all those configs and repo lists together :v