Let me go back to the top and answer the original questions, then offer a few 
thoughts that have been germinating in my head through this discussion.

Chris Angelico wrote:
> I've just updated PEP 671 https://www.python.org/dev/peps/pep-0671/
> with some additional information about the reference implementation,
> and some clarifications elsewhere.
> *PEP 671: Syntax for late-bound function argument defaults*
> Questions, for you all:
> 1) If this feature existed in Python 3.11 exactly as described, would
> you use it?

Yes, but reluctantly. I take advantage of the features the language I'm using 
offers, even if I dislike them. And I greatly dislike this and would rather not 
have it for reasons described below.

> 2) Independently: Is the syntactic distinction between "=" and "=>" a
> cognitive burden?
> (It's absolutely valid to say "yes" and "yes", and feel free to say
> which of those pulls is the stronger one.)

Yes. When a single punctuation character distinguishes between two closely 
related but significantly different behaviors, that is a large cognitive burden 
because it slows down code reading. I am used to scanning through unfamiliar 
code quickly, as I frequently go through the code of third-party modules, and 
if this becomes a thing, I would have to stop and slow down to check whether 
argument defaults are being bound early or late to comprehend the code I'm 
reading. I don't want that.

> 3) If "yes" to question 1, would you use it for any/all of (a) mutable
> defaults, (b) referencing things that might have changed, (c)
> referencing other arguments, (d) something else?

Whatever appropriate uses arise. Most likely that would be mutable defaults 
like `[]` and `{}`. Referencing other arguments might be useful as well. I 
don't see any use for (b) in my code.

> 4) If "no" to question 1, is there some other spelling or other small
> change that WOULD mean you would use it? (Some examples in the PEP.)

Well, my answer to Q1 was "yes but I'd rather not". Frankly, there is no 
similar spelling that sounds reasonable to me.

> 5) Do you know how to compile CPython from source, and would you be
> willing to try this out? Please? :)

Yes, but no. Because I hate it. ;)

> I'd love to hear, also, from anyone's friends/family who know a bit of
> Python but haven't been involved in this discussion. If late-bound
> defaults "just make sense" to people, that would be highly
> informative.

Late-bound defaults absolutely "just make sense". Way more sense than 
early-bound to me. This is reflected in the review of languages that Steven 
D'Aprano did a few days ago, where 80% of languages with syntax for default 
argument values use late binding, and all that bind early restrict default 
values to constants. Thus, when non-constant values are allowed as default 
values, current Python is entirely unique (among that list) in doing early 
binding. Early binding of non-constants has too many "gotcha"s and no real 
benefits, and any decent language being developed today ought to use late 
binding.

Unfortunately, we can't remake the past. Python is stuck with the wart of early 
binding. Note that on that list of languages Steven produced, **none** offer 
both early and late binding. Arguably, offering both and expecting users to 
grok which is which is *worse* than the current wart of a single behavior that 
works in one way and is not difficult to work around. And therefore I believe 
that Python should not in any case offer both behaviors simultaneously.

My preferences to resolve this are, in order:

1. Introduce `from __future__ import late_default`. When present, argument 
defaults in that file are late bound instead of early bound. After a suitable 
deprecation period, make the future statement the default behavior. Then Python 
will comply with best practices demonstrated by Steven's language review. I 
have not done any analysis, but I believe based on intuition that any breakage 
in libraries and scripts stemming from this would be relatively easy to fix, 
and most existing code should just work (in particular, the common existing 
usage of a sentinel as a default with an `is None` or `is sentinel` check in 
the body would not break and could be migrated to the new behavior at leisure). 
If true, it would result in minimal fuss for maximum benefit. 

2. If a future statement and behavior change is deemed too disruptive, then 
keep early binding, do not introduce late binding, and introduce a new use for 
the keyword `pass` to represent an absent argument. Under this idea, `pass` 
would be accepted as an expression in the following three contexts, and exactly 
nowhere else: a) as a complete argument to a call, b) as a complete "value" for 
an argument default, and c) in the expressions `x is pass` and `x is not pass`, 
but only when both `x` is a parameter to the immediately enclosing function and 
the default value of that parameter is `pass`. This way, `pass` acts as a 
sentinel that isn't a valid value in any other context, which would solve the 
issue of when `None` is a valid value.

3. If both of those are undesired, then keep the wart in the status quo, and 
don't add late binding in any form.

> Any and all comments welcomed. I mean, this is python-ideas after
> all... bikeshedding is what we do best!

Let's build a garage instead. ;)
_______________________________________________
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/KE55HJN2N4RZ3TH5JCE5WXQDLGTJXQ3K/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to