On Apr 16, 2020, at 21:42, oliveira.rodrig...@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.
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/WB7TCF3JFAHS7BKIYV4CCDPXOW32LBZ3/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to