PEP 572: Updates in response to posting #3 :)

This commit is contained in:
Chris Angelico 2018-03-24 05:10:41 +11:00
parent ab86d06172
commit 3541449faf
1 changed files with 31 additions and 11 deletions

View File

@ -12,18 +12,23 @@ Post-History: 28-Feb-2018, 02-Mar-2018, 23-Mar-2018
Abstract
========
Programming is all about reusing code rather than duplicating it. When
an expression needs to be used twice in quick succession but never again,
it is convenient to assign it to a temporary name with small scope.
By permitting name bindings to exist within a single statement only, we
make this both convenient and safe against name collisions.
This is a proposal for permitting temporary name bindings
which are limited to a single statement.
Rationale
=========
When a subexpression is used multiple times in a list comprehension, there
are currently several ways to spell this, none of which is universally
Programmers generally prefer reusing code rather than duplicating it. When
an expression needs to be used twice in quick succession but never again,
it is convenient to assign it to a temporary name with small scope.
By permitting name bindings to exist within a single statement only, we
make this both convenient and safe against name collisions.
This is particularly notable in list/dict/set comprehensions and generator
expressions, where refactoring a subexpression into an assignment statement
is not possible. There are currently several ways to create a temporary name
binding inside a list comprehension, none of which is universally
accepted as ideal. A statement-local name allows any subexpression to be
temporarily captured and then used multiple times.
@ -43,7 +48,13 @@ and ``NAME`` is a simple name.
The value of such a named expression is the same as the incorporated
expression, with the additional side-effect that NAME is bound to that
value for the remainder of the current statement.
value for the remainder of the current statement. For example::
# Similar to the boolean 'or' but checking for None specifically
x = "default" if (spam().ham as eggs) is None else eggs
# Even complex expressions can be built up piece by piece
y = ((spam() as eggs), (eggs.method() as cheese), cheese[eggs])
Just as function-local names shadow global names for the scope of the
function, statement-local names shadow other names for that statement.
@ -252,14 +263,14 @@ Both of these are forbidden; creating SLNBs in the headers of these statements
will result in a SyntaxError.
Alternative proposals
=====================
Alternative proposals and variants
==================================
Proposals broadly similar to this one have come up frequently on python-ideas.
Below are a number of alternative syntaxes, some of them specific to
comprehensions, which have been rejected in favour of the one given above.
1. ``where``, ``let``, ``given``::
1. ``where``, ``let``, or ``given``, in comprehensions only::
stuff = [(y, x/y) where y = f(x) for x in range(5)]
stuff = [(y, x/y) let y = f(x) for x in range(5)]
@ -337,6 +348,15 @@ comprehensions, which have been rejected in favour of the one given above.
``f(x) < 0`` and you want to capture the value of ``f(x)``). It also has
no benefit to list comprehensions.
8. Adding a ``where:`` to any statement to create local name bindings::
value = x**2 + 2*x where:
x = spam(1, 4, 7, q)
Execution order is inverted (the indented body is performed first, followed
by the "header"). This requires a new keyword, unless an existing keyword
is repurposed (most likely ``with:``).
Discrepancies in the current implementation
===========================================