>From what I've seen so far, I'm -0 on this.

I understand the pattern it addresses, but it doesn't feel all that common,
nor that hard to address with the existing sentinel-check pattern alien in
the PEP draft.

This just doesn't feel big enough to merit it's own syntax.

... On the other hand, if this could express a much more general deferred
computation, I'd be really enthusiastic (subject to syntax and behavioral
details).

However, I recognize that a new general "dynamically scoped lambda" would
indeed have a lot of edge cases.


On Sat, Oct 23, 2021, 8:15 PM Chris Angelico <ros...@gmail.com> wrote:

> Incorporates comments from the thread we just had.
>
> Is anyone interested in coauthoring this with me? Anyone who has
> strong interest in seeing this happen - whether you've been around the
> Python lists for years, or you're new and interested in getting
> involved for the first time, or anywhere in between!
>
> https://www.python.org/dev/peps/pep-0671/
>
> PEP: 671
> Title: Syntax for late-bound function argument defaults
> Author: Chris Angelico <ros...@gmail.com>
> Status: Draft
> Type: Standards Track
> Content-Type: text/x-rst
> Created: 24-Oct-2021
> Python-Version: 3.11
> Post-History: 24-Oct-2021
>
>
> Abstract
> ========
>
> Function parameters can have default values which are calculated during
> function definition and saved. This proposal introduces a new form of
> argument default, defined by an expression to be evaluated at function
> call time.
>
>
> Motivation
> ==========
>
> Optional function arguments, if omitted, often have some sort of logical
> default value. When this value depends on other arguments, or needs to be
> reevaluated each function call, there is currently no clean way to state
> this in the function header.
>
> Currently-legal idioms for this include::
>
>     # Very common: Use None and replace it in the function
>     def bisect_right(a, x, lo=0, hi=None, *, key=None):
>         if hi is None:
>             hi = len(a)
>
>     # Also well known: Use a unique custom sentinel object
>     _USE_GLOBAL_DEFAULT = object()
>     def connect(timeout=_USE_GLOBAL_DEFAULT):
>         if timeout is _USE_GLOBAL_DEFAULT:
>             timeout = default_timeout
>
>     # Unusual: Accept star-args and then validate
>     def add_item(item, *optional_target):
>         if not optional_target:
>             target = []
>         else:
>             target = optional_target[0]
>
> In each form, ``help(function)`` fails to show the true default value. Each
> one has additional problems, too; using ``None`` is only valid if None is
> not
> itself a plausible function parameter, the custom sentinel requires a
> global
> constant; and use of star-args implies that more than one argument could be
> given.
>
> Specification
> =============
>
> Function default arguments can be defined using the new ``=>`` notation::
>
>     def bisect_right(a, x, lo=0, hi=>len(a), *, key=None):
>     def connect(timeout=>default_timeout):
>     def add_item(item, target=>[]):
>
> The expression is saved in its source code form for the purpose of
> inspection,
> and bytecode to evaluate it is prepended to the function's body.
>
> Notably, the expression is evaluated in the function's run-time scope, NOT
> the
> scope in which the function was defined (as are early-bound defaults). This
> allows the expression to refer to other arguments.
>
> Self-referential expressions will result in UnboundLocalError::
>
>     def spam(eggs=>eggs): # Nope
>
> Multiple late-bound arguments are evaluated from left to right, and can
> refer
> to previously-calculated values. Order is defined by the function,
> regardless
> of the order in which keyword arguments may be passed.
>
>
> Choice of spelling
> ------------------
>
> Our chief syntax proposal is ``name=>expression`` -- our two syntax
> proposals
> ... ahem. Amongst our potential syntaxes are::
>
>     def bisect(a, hi=>len(a)):
>     def bisect(a, hi=:len(a)):
>     def bisect(a, hi?=len(a)):
>     def bisect(a, hi!=len(a)):
>     def bisect(a, hi=\len(a)):
>     def bisect(a, hi=`len(a)`):
>     def bisect(a, hi=@len(a)):
>
> Since default arguments behave largely the same whether they're early or
> late
> bound, the preferred syntax is very similar to the existing early-bind
> syntax.
> The alternatives offer little advantage over the preferred one.
>
> How to Teach This
> =================
>
> Early-bound default arguments should always be taught first, as they are
> the
> simpler and more efficient way to evaluate arguments. Building on them,
> late
> bound arguments are broadly equivalent to code at the top of the function::
>
>     def add_item(item, target=>[]):
>
>     # Equivalent pseudocode:
>     def add_item(item, target=<OPTIONAL>):
>         if target was omitted: target = []
>
>
> Open Issues
> ===========
>
> - yield/await? Will they cause problems? Might end up being a non-issue.
>
> - annotations? They go before the default, so is there any way an anno
> could
>   want to end with ``=>``?
>
>
> References
> ==========
>
>
> Copyright
> =========
>
> This document is placed in the public domain or under the
> CC0-1.0-Universal license, whichever is more permissive.
> _______________________________________________
> 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/KR2TMLPFR7NHDZCDOS6VTNWDKZQQJN3V/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
_______________________________________________
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/JSPTTDFLNZSVXAHQ4I4FAUWYE7VC2M4U/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to