
On Apr 16, 2020, at 21:42, oliveira.rodrigo.m@gmail.com wrote:
I believe this is a different feature, non-exclusive to the one proposed here, that would also make it possible not to re-declare keywords.
Yes, it is a different feature from magic call syntax. And yes, theoretically they’re non-exclusive and we could add both, but practically it would eliminate the need for the magic call syntax feature (as well as having other uses), so we almost surely wouldn’t add both. That’s the point of describing it in this thread: it solves the same problem in a different, and I think better, way.
But implementing this change with the argument of making function calls less repetitive or verbose when having redundant named keywords and variables doesn't sell it to me.
See, function calls would still suffer to be less redundant if we go with this:
```python def foo(a, b, **kwargs): c = ... bar(**{:a, :b, :c, d: kwargs["d"]}) # this just got worse ```
Nobody’s forcing you to put all keywords into the dict. Today, you can mix **dict and normal keywords in a function call (and in a dict literal, and anywhere else **unpacking is allowed), and that isn’t going to go away, so you’d just write: bar(**(:a, :b, :c), d=kwargs['d']) Note that this is different from any magic call syntax. If you want to allow normal keyword arguments to mix with magic ones in a magic call syntax, you have to specify some additional syntax for doing that. With my proposal, you don’t, because the existing call syntax and **unpacking syntax already handle that today, and I’m not changing them.
```python def foo(a, b, **kwargs): c = ... # all parameters definition is away from the function call, not a fan # one can possibly overwrite some key on kwarg without knowing kwargs.update({:a, :b, :c}) bar(**kwargs) ```
Sure, if you want to write that you can, or you can also write this: bar(**kwargs, **{:a, :b, :c}) And again, this is exactly the way things already work. If you have two separate dicts of keyword arguments, you can ** them both, or you can merge them and ** the result, and there are advantages and disadvantages of each that people already choose between, and nothing about that changes with this proposal. If you’re not a fan of one way of doing it, you already presumably use the other, and that won’t change. The only thing that changes is that your dict display, wherever you choose to put it, gets shorter.
```python def foo(a, b, **kwargs): c = ... bar(**(kwargs | {:a, :b, :c})) # a little better but one can still overwrite some key on kwarg without knowing ```
Yes, 3.8 gives you this third option, so people already use it when appropriate today and hopefully don’t use it when it isn’t. And that also won’t change just because the second dict becomes easier to construct.
Using a "magical" separator does the job and has little interactions with other syntaxes,
And adding magic to dict displays also does the job and also has little interaction with other syntaxes. In fact, it has even less interaction with other syntaxes, because the dict display is completely independent of the call syntax and therefore can be refactored out of the call, like any other dict. bar(**{:a, :b, :c}) kw = {:a, :b, :c} bar(**kw) … or used anywhere else a dict can be **’d, like another dict display. Or even in a place where there’s no ** going on: userlist.append({:name, :email, :phone}) json.dump(userlistfile, userlist)
using the `*` character seems better than just picking another random one (like we did with `/`). Comparing with all the above excerpts, this is still more appealing and clearer for me:
```python def foo(a, b, **kwargs): c = ... bar(*, a, b, c, **kwargs) # also, if any of `a`, `b` or `c` is in `kwargs` we get a proper error ```
Well, this doesn’t do the same thing as your earlier examples. And if you want this with my syntax: bar(**{:a, :b, :c}, **kwargs) … you get that exact same benefit of an error if kwargs has an a in it. And you even get that benefit if you refactor the dict into a temporary variable because the call got too long or complex to read, or because you needed that dict for some other purpose (maybe just a debug print), or whatever. Because, again, my proposal changes nothing about call syntax or ** unpacking, and therefore all the things that already work—like detecting repeated keywords from separate unpackings—continue to work. And that’s the advantage of this proposal in a nutshell—I didn’t think about repeated keyword detection until you brought it up, so I didn’t work out a way to make it work, but that’s fine. Because I’m not adding anything new to calls, everything that needs to be thought through already has been thought through, designed, implemented, taught, and used in the field for years, as part of the existing call and **unpacking syntax and semantics that already work. The magic * has few interactions with the rest of call, but changing dict displays has zero interactions, which is even better than few.