Skip to content

Commit

Permalink
PEP 572: Updates in response to posting #3 :)
Browse files Browse the repository at this point in the history
  • Loading branch information
Rosuav committed Mar 23, 2018
1 parent ab86d06 commit 3541449
Showing 1 changed file with 31 additions and 11 deletions.
42 changes: 31 additions & 11 deletions pep-0572.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand All @@ -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.
Expand Down Expand Up @@ -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)]
Expand Down Expand Up @@ -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
===========================================
Expand Down

0 comments on commit 3541449

Please sign in to comment.