Attempting to bring things back on topic to function parameters with 
late binding.

On Fri, May 29, 2020 at 06:03:30PM +0200, Alex Hall wrote:

> Chris was just saying that a statement like `x ?= y` meaning 'assign the
> value of y to the local variable x if x is currently unbound' already fits
> neatly into the language model and doesn't require major changes. Do you
> disagree?
> 
> (although I don't endorse the proposal for `x ?= y`)

I have no idea whether `?=` alone requires major changes or not.
Probably not, since we can already implement it as a try...except:

    try:
        x
    except NameError:
        x = y

But as the proposal relates to function calls, it is a big change that 
will turn early detection of some errors into late detection.

Consider what happens when you call a function. The interpreter matches 
up arguments supplied in the function call to parameters in the function 
signature. If any parameters don't get an argument, the intrepreter 
provides default values. If, after applying defaults, any parameter 
doesn't have a value then the intrepreter raises TypeError, otherwise it 
calls the function and enters the body of the function.

The consequence of this is that if the function body is entered, it is
impossible for any parameter to be unbound.

    def spam(arg):
        # if we enter the body of the function, then arg must be
        # bound and `arg ?= ...` will never apply.

That means that Chris' proposed `?=` operator would not help at all to
get late-binding defaults. Adding a bind-only-if-unbound operator might
be useful, or not, but it doesn't solve the mutable default issue.

In order to solve the mutable default issue, the intrepreter has to stop
raising TypeError, and instead enter the function body with the function
parameters left unbound. So exceptions like this will disappear:

    py> len()
    TypeError: len() takes exactly one argument (0 given)

to be replaced with something like this:

    UnboundLocalError: local variable referenced before assignment

when the function tries to access the unbound parameter.

And we change code currently written like this:

    def spam(arg=None):
        if arg is None:
            arg = expression

into code written like this:

    def spam(arg):
        arg ?= expression

which saves one line, not much benefit to gain for the pain.

So a general purpose `?` bind-if-unbound operator doesn't solve the 
problem at hand, even if it were useful in other ways.

What if it wasn't a general purpose operator, but instead special 
syntax that applies only in function signatures? Then we could write:

    def spam(arg?=expression):

and the rule for the interpreter would become:

Match up arguments supplied in the function call to parameters in the 
function signature. If any parameters don't get an argument, apply 
default values:

- if the default is set with `=`, it is early-bound and nothing 
  changes from today;

- if the default is set with `?=` it is late-bound and the default
  is re-evaluated as needed;

Finally, if after applying defaults, any parameter doesn't have a value, 
then the intrepreter raises TypeError, otherwise it calls the function 
and enters the body of the function.

The concept of bound-or-unbound doesn't come into this, or at least no 
more that it already applies to the status quo. The whole process takes 
place before the function is called. The only differences from the 
status quo are that the `?` tells:

- the compiler to delay evaluating the default and store the expression 
  itself (in some format), rather than evaluate the expression and store 
  the evaluated value;

- the interpreter to re-evaluate that expression, not just fetch the 
  pre-evaluated value.

Is that a big change or hard to implement? I don't know.


-- 
Steven
_______________________________________________
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/PEHDA3FAFOZSD43MVI4GK24MSW4A5LQH/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to