On Apr 21, 2020, at 01:27, M.-A. Lemburg <[email protected]> wrote:
> 
> On 21.04.2020 04:25, Andrew Barnert via Python-ideas wrote:
>>> On Apr 20, 2020, at 16:24, M.-A. Lemburg <[email protected]> wrote:
>>> 
>>> On 20.04.2020 19:43, Andrew Barnert via Python-ideas wrote:
>>>>> On Apr 20, 2020, at 01:06, M.-A. Lemburg <[email protected]> wrote:
>>>>> 
>>>>> The current version already strikes me as way too complex.
>>>>> It's by far the most complex piece of grammar we have in Python:
>>>>> 
>>>>> funcdef: 'def' NAME parameters ['->' test] ':' [TYPE_COMMENT]
>>>>> func_body_suite
>>>> 
>>>> But nobody’s proposing changing the function definition syntax here, only 
>>>> the function call syntax. Which is a lot less hairy. It is still somewhat 
>>>> hairy, but nowhere near as bad, so this argument doesn’t really apply.
>>> 
>>> True, I quoted the wrong part of the grammar for the argument,
>>> sorry. I meant this part:
>>> 
>>> https://docs.python.org/3/reference/expressions.html#calls
>>> 
>>> which is simpler, but not really much, since the devil is in
>>> the details.
>> 
>> Let’s just take one of the variant proposals under discussion here, adding 
>> ::identifier to dict displays. This makes no change to the call grammar, or 
>> to any of the call-related bits, or any other horribly complicated piece of 
>> grammar. It just changes key_datum (a nonterminal referenced only in 
>> dict_display) from this:
>> 
>>    expression ":" expression | “**” or_expr
>> 
>> … to this:
>> 
>>    expression ":" expression | “::” identifier | “**” or_expr
>> 
>> That’s about as simple as any syntax change ever gets.
>> 
>> Which is still not nothing. But you’re absolutely right that a big and messy 
>> change to function definition grammar would have a higher bar to clear than 
>> most syntax proposals—and for the exact same reason, a small and local 
>> change to dict display datum grammar has a lower bar than most syntax 
>> proposals.
> 
> I think the real issue you would like to resolve is how to get
> at the variable names used for calling a function, essentially
> pass-by-reference (in the Python sense, where variable names are
> references to objects, not pointers as in C) rather than
> pass-by-value, as is the default for Python functions.

No, nobody’s asking for that either.

It wouldn’t directly solve most of the examples in this thread, or even 
indirectly make them easier to solve. The problem in most cases is that they 
have to call a function that they can’t change with a big mess of parameters. 
Any change to help the callee side doesn’t do any good, because the callee is 
the thing they can’t change. The fix needs to be on the caller side alone.

This also wouldn’t give you useful pass-by-reference in the usual sense of “I 
want to let the callee rebind the variables I pass in”, because a name isn’t a 
reference in Python without the namespace to look it up in. Even if the callee 
knew the name the caller used for one of its parameters, how would it know 
whether that name was a local or a cell or a global? If it’s a local, how would 
it get at the caller’s local environment without frame hacking? (As people have 
demonstrated on this thread, frame hacking on its own is enough, without any 
new changes.) Even if it could get that local environment, how could it rebind 
the variable when you can’t mutate locals dicts?

Also, most arguments in Python do not have names, because arguments are 
arbitrary expressions. Of course the same thing is true in, say, C++, but 
that’s fine in C++, because lvalue expressions have perfectly good lvalues even 
if they don’t have good names. You can pass p->vec[idx+1].spam to a function 
that wants an int&, and it can modify its parameter and you’ll see the change 
on your side. How could your proposal handle even the simplest case of passing 
lst[0]?

Even if it could work as advertised, it’s hugely overkill for this problem. A 
full-blown macro system would let people solve this problem, and half the other 
things people propose for Python, but that doesn’t mean that half the proposals 
on this list are requests for a full-blown macro system, or that it’s the right 
answer for them.

> The f-string logic addresses a similar need.

Similar, yes, but the f-string logic (a) runs in the caller’s scope and (b) 
evaluates code that’s textually part of the caller.

> With a way to get at the variable names used for calling a
> function from inside a function, you could then write a dict
> constructor which gives you the subset of vars() you are
> looking for.

Most of the use cases involve “I can’t change the callee, so I need to give it 
the ugly mess of keyword args that it wants”. So any proposal to allow changing 
callees is already on the wrong track.

But even if this were acceptable, how would it help anything? Take any of the 
examples from this thread, ignore the “I can’t change the function I’m calling 
part”, and show how you’d solve it if the callee had the caller’s names for its 
parameters.

Also, “you can solve this with ugly introspection code” does not always mean we 
don’t need a better solution. In fact, you can solve this today, from the 
caller side, with something like this (not in front of a computer right now, so 
probably most of the details are wrong, but hopefully you can get the idea):

    sig = inspect.signature(spam)
    spamargs = {k: v for (k, v) in vars().items() if k in sig.kwargs}
    spam(**spamargs)

… but it should be obvious why nobody writes that code rather than:

    spam(eggs=eggs, cheese=cheese, ham=ham)

They want a way to make things less verbose and less error prone, and I just 
offered them a way to make things more verbose and more error prone, and I 
doubt any of them will take it. You’re offering them a way to rewrite the 
function they can’t rewrite so they can have another way to make things more 
verbose and more error prone and also more unsafe and nonportable, and I doubt 
that will be any more helpful.

> Rather than using new syntax, a helper in the compiler would
> do the trick, though, similar to what e.g. @classmethod
> does.

@classmethod doesn’t have any help from the compiler. It’s a trivial use of the 
same __get__ protocol, which you could write yourself.

And it’s not clear what kind of compiler helper you could use for your idea. 
Remember that when compiling a call, the compiler has no idea what the callable 
is; it can’t know, because that’s completely dynamic. So anything you want to 
magically sweep up and package from the caller side has to be passed in to 
every call. You surely wouldn’t want to pass along the name of every argument 
in every call? That would be a huge backward compatibility break and a huge 
performance cost, and also impossible because most arguments don’t have names.
_______________________________________________
Python-ideas mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/[email protected]/message/ORC36RKGHMJAHVR55M22U5CWXAHS4ZR4/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to