On 14 Jul 2019, at 20:21, Andrew Barnert <abarnert@yahoo.com> wrote:
On Jul 14, 2019, at 00:33, Anders Hovmöller <boxed@killingar.net> wrote:
This use case is nicely covered by short form for keyword arguments. So in this case instead of plot(x, z), we'd have plot(=x, =z) which would be transformed into plot(**{'x': x, 'z': z}) at compile time.
This does avoid the problem of needing new syntax, but it seems to have other problems.
Well it does introduce new syntax, just one that is generally useful.
First, the function only gets the names, not live expressions that it can eval late, or in a modified environment, etc., so it only handles this case, not cases like df[year>1990].
I don't understand how it's not the full expression. It's the expression as a string but it's still the full code.
Second, the names show up as keyword argument names, not as values. Besides being a bit confusing to mix up names and values this way, it means everything has to be defined as def plot(**kwargs) and document its actual arguments some other way, and can’t annotate the parameter types, and if there are optional like the ones pyplot takes for point formatting, scale, etc., there’s no protection against them colliding with the names of the two fake-positional args.
I think names being put with names isn't confusing ;) But yes, a system like this would probably need other tweaks for API design but that's to be expected.
This could work for any expression:
foo(=lamda x: x*2) -> foo(**{'lamda x: x*2': lamda x: x*2})
Is this actually legal? The docs just say the contents of the ** mapping are treated as additional keyword arguments. CPython happens to check that they are strings but not check that those strings are valid keywords, but I don’t think the language definition actually says this is the intended behavior, it’s just an accident of the CPython implementation. So this might require at least defining that implementation behavior as the only correct one, and changing the docs to explain it.
You are correct. I have checked that this is the behavior of CPython, pypy, micropythob, iron python, and jython so shouldn't be a big burden.
Also, is this translation literally the way it’s implemented? Does that mean bare keyword args can only appear in a call expression in the same place as **, even though they don’t look similar?
Can be implemented. Not is. It's a suggestion.
This feature is easy to implement and has broad applications.
How is this implemented? Doesn’t the compiler have the same problem generating a string for the keyword out of an AST that the user code would have in the OP’s proposal?
Sure. The lack of round tripping in the standard library AST is a problem but in this case a simple AST dump is most likely fine even if it loses the users specific formatting.
Also, what are the other applications besides the plot example and equivalent things? I would guess the main uses are actually really simple cases. For example, in a lot of short, simple functions, you often create variables named x and y for the things you’re going to pass as the x and y arguments to plot, and sometimes even xscale; similarly for the url argument to requests.get; and so on. All of these get a few characters shorter to type and read (and maybe a bit harder to accidentally screw up) if you can write “=x” instead of “x=x”. But are there other benefits, for less trivial cases?
You are correct that this a big benefit in many small doses. There are some nice use cases like being able to create a debug printer that is very good. It's also very useful for us web developers because we often need to put a bunch of variables in a template context dict. / Anders