
On Apr 16, 2020, at 12:05, Dominik Vilsmeier <dominik.vilsmeier@gmx.de> wrote:
I'm not sure if this is doable from the compiler perspective, but what about allowing tuples after `**` unpacking:
requests.post(url, **(data, params))
# similar to requests.post(url, data=data, params=params)
Is this actually a tuple? So the items can be any expression at all? Then what’s the keyword for, say, `requests.post(url, **(data, timeout*2))`? Also, could you use **tuple in other contexts where **unpacking is allowed, like dict displays, or only in calls? If we’re going to build on ** unpacking, maybe instead of coming up with special syntax that works everywhere **unpacking does, or that only works in some places **unpacking does, it would be simpler/cleaner to come up with special syntax just for dict displays—which automatically gives you the ability to **unpack in calls and anywhere else? Here’s a straw man. A one-liner grammar change is all you need, and restricting it to just identifiers is easy: key_datum ::= expression ":" expression | "**" or_expr | ":" identifier And the semantics of the new third form would be that the key is the name of the identifier as a string and the value is the value of the identifier as an expression. And here’s what it looks like: requests.post(url, **{:data, :params}) The obvious way to mix normal and magic keywords just works; you can of course write this: requests.post(url, headers=makeheaders(), **{:data, :params}) … but if headers has to come after data for some reason you can do this: requests.post(url, **{:data, "headers": makeheaders(), :params}) … or, if you prefer, this: requests.post(url, **{:data}, headers=makeheaders(), **{:params}) … because we’re just using the already-working, well-understood rules for **unpacking. And it can also be used outside of calls: params = {:name, :email, "phone": formatphone(phone)} request.post(url, json=params) … which also means you could refactor a really hairy call in an obvious way: kw = { :data, "headers": makeheaders(), :params } requests.post(url, **kw) Extending it beyond identifiers might be useful, but there are enough potential problems and questions (e.g., is the name of :spam.eggs “spam.eggs” or “eggs”?) that it would almost certainly be worth putting off to a future version after people have gotten experience with the basic feature. I’m not sure if I like this syntax, but I do like it better than the magic * separator syntax and the magic **-unpack-a-tuple syntax. (And I like the overall idea in this thread if someone can come up with good enough syntax.)