[Python-checkins] r82991 - in peps/trunk: pep-3150.txt pep0/pep.py
nick.coghlan
python-checkins at python.org
Tue Jul 20 15:17:13 CEST 2010
Author: nick.coghlan
Date: Tue Jul 20 15:17:13 2010
New Revision: 82991
Log:
Make error message slightly more helpful in diagnosing missing angle brackets around an email address in the PEP header
Added:
peps/trunk/pep-3150.txt (contents, props changed)
Modified:
peps/trunk/pep0/pep.py
Added: peps/trunk/pep-3150.txt
==============================================================================
--- (empty file)
+++ peps/trunk/pep-3150.txt Tue Jul 20 15:17:13 2010
@@ -0,0 +1,274 @@
+PEP: 3150
+Title: Statement local namespaces (aka "where" clause)
+Version: $Revision$
+Last-Modified: $Date$
+Author: Nick Coghlan <ncoghlan at gmail.com>
+Status: Deferred
+Type: Standards Track
+Content-Type: text/x-rst
+Created: 2010-07-09
+Python-Version: 3.3
+Post-History: 2010-07-14
+Resolution: TBD
+
+
+Abstract
+========
+
+A recurring proposal on python-ideas is the addition of some form of
+statement local namespace.
+
+This PEP is intended to serve as a focal point for those ideas, so we
+can hopefully avoid retreading the same ground a couple of times a
+year. Even if the proposal is never accepted having a PEP to point
+people to can be valuable (e.g. having PEP 315 helps greatly in avoiding
+endless rehashing of loop-and-a-half arguments).
+
+The ideas in this PEP are just a sketch of a way this concept might work.
+They avoid some pitfalls that have been encountered in the past, but
+have not themselves been subject to the test of implementation.
+
+
+PEP Deferral
+============
+
+This PEP is currently deferred at least until the language moratorium
+(PEP 3003) is officially lifted by Guido. Even after that, it will
+require input from at least the four major Python implementations
+(CPython, PyPy, Jython, IronPython) on the feasibility of implementing
+the proposed semantics to get it moving again.
+
+Proposal
+========
+
+This PEP proposes the addition of an optional "where" clause to the
+syntax for simple statements which may contain an expression. The
+current list of simple statements that would be affected by this
+addition is as follows:
+
+* expression statement
+* assignment statement
+* augmented assignment statement
+* del statement
+* return statement
+* yield statement
+* raise statement
+* assert statement
+
+The ``where`` clause would allow subexpressions to be referenced by
+name in the header line, with the actual definitions following in
+the indented clause. As a simple example::
+
+ c = sqrt(a*a + b*b) where:
+ a = retrieve_a()
+ b = retrieve_b()
+
+Torture Test
+============
+
+An implementation of this PEP must support execution of the following
+code at module, class and function scope::
+
+ b = {}
+ a = b[f(a)] = x where:
+ x = 42
+ def f(x):
+ return x
+ assert "x" not in locals()
+ assert "f" not in locals()
+ assert a == 42
+ assert d[42] == 42 where:
+ d = b
+ assert "d" not in locals()
+
+Most naive implementations will choke on the first complex assignment,
+while less naive but still broken implementations will fail when
+the torture test is executed at class scope.
+
+And yes, that's a perfectly well-defined assignment statement. Insane,
+I agree, but legal::
+
+ >>> def f(x): return x
+ ...
+ >>> x = 42
+ >>> b = {}
+ >>> a = b[f(a)] = x
+ >>> a
+ 42
+ >>> b
+ {42: 42}
+
+
+Syntax Change
+=============
+
+Current::
+
+ expr_stmt: testlist_star_expr (augassign (yield_expr|testlist) |
+ ('=' (yield_expr|testlist_star_expr))*)
+ del_stmt: 'del' exprlist
+ return_stmt: 'return' [testlist]
+ yield_stmt: yield_expr
+ raise_stmt: 'raise' [test ['from' test]]
+ assert_stmt: 'assert' test [',' test]
+
+
+New::
+
+ expr_stmt: testlist_star_expr (augassign (yield_expr|testlist) |
+ ('=' (yield_expr|testlist_star_expr))*) [where_clause]
+ del_stmt: 'del' exprlist [where_clause]
+ return_stmt: 'return' [testlist] [where_clause]
+ yield_stmt: yield_expr [where_clause]
+ raise_stmt: 'raise' [test ['from' test]] [where_clause]
+ assert_stmt: 'assert' test [',' test] [where_clause]
+ where_clause: "where" ":" suite
+
+(Note that expr_stmt in the grammar covers assignment and augmented
+assignment in addition to simple expression statements)
+
+The new clause is added as an optional element of the existing statements
+rather than as a new kind of compound statement in order to avoid creating
+an ambiguity in the grammar. It is applied only to the specific elements
+listed so that nonsense like the following is disallowed::
+
+ pass where:
+ a = b = 1
+
+However, even this is inadequate, as it creates problems for the definition
+of simple_stmt (which allows chaining of multiple single line statements
+with ";" rather than "\n").
+
+So the above syntax change should instead be taken as a statement of intent.
+Any actual proposal would need to resolve the simple_stmt parsing problem
+before it could be seriously considered. This would likely require a
+non-trivial restructuring of the grammar, breaking up small_stmt and
+flow_stmt to separate the statements that potentially contain arbitrary
+subexpressions and then allowing a single one of those statements with
+a ``where`` clause at the simple_stmt level. Something along the lines of::
+
+ simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
+ where_stmt: subexpr_stmt (where_clause | (';' small_stmt)* [';']) NEWLINE
+ subexpr_stmt: expr_stmt | del_stmt | flow_subexpr_stmt | assert_stmt
+ small_stmt: (pass_stmt | flow_stmt | import_stmt |
+ global_stmt | nonlocal_stmt)
+ flow_stmt: break_stmt | continue_stmt
+ flow_subexpr_stmt: return_stmt | raise_stmt | yield_stmt
+ where_clause: "where" ":" suite
+
+
+For reference, here are the current definitions at that level::
+
+ simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
+ small_stmt: (expr_stmt | del_stmt | pass_stmt | flow_stmt |
+ import_stmt | global_stmt | nonlocal_stmt | assert_stmt)
+ flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt
+
+
+Common Objections
+=================
+
+* Two Ways To Do It: a lot of code may now be written with values
+ defined either before the expression where they are used or
+ afterwards in a ``where`` clause, creating two ways to do it,
+ without an obvious way of choosing between them.
+
+* Out of Order Execution: the ``where`` clause makes execution
+ jump around a little strangely, as the body of the ``where``
+ clause is executed before the simple statement in the clause
+ header. The closest any other part of Python comes to this
+ before is the out of order evaluation in conditional
+ expressions.
+
+
+Possible Additions
+==================
+
+* The current proposal allows the addition of a ``where`` clause only
+ for simple statements. Extending the idea to allow the use of
+ compound statements would be quite possible, but doing so raises
+ serious readability concerns (as values defined in the ``where``
+ clause may be used well before they are defined, exactly the kind
+ of readability trap that decorators were designed to eliminate)
+
+* Currently only the outermost clause of comprehensions and generator
+ expressions can reference the surrounding namespace when executed
+ at class level. If this proposal is implemented successfully, the
+ associated namespace semantics could allow that restriction to be
+ lifted. There would be backwards compatibility implications in doing
+ so as existing code may be relying on the behaviour of ignoring
+ class level variables.
+
+Possible Implementation Strategy
+================================
+
+AKA How Class Scopes Screw You When Attempting To Implement This
+
+The natural idea when setting out to implement this concept is to
+use an ordinary nested function scope. This doesn't work for the
+two reasons mentioned in the Torture Test section above:
+
+* Non-local variables are not your friend because they ignore class scopes
+ and (when writing back to the outer scope) aren't really on speaking
+ terms with module scopes either.
+
+* Return-based semantics struggle with complex assignment statements
+ like the one in the torture test
+
+The most promising approach is one based on symtable analysis and
+copy-in-copy-out referencing semantics to move any required name
+bindings between the inner and outer scopes. The torture test above
+would then translate to something like the following::
+
+ b = {}
+ def _anon1(b): # 'b' reference copied in
+ x = 42
+ def f(x):
+ return x
+ a = b[f(a)] = x
+ return a # 'a' reference copied out
+ a = _anon1(b)
+ assert "x" not in locals()
+ assert "f" not in locals()
+ assert a == 42
+ def _anon2(b) # 'b' reference copied in
+ d = b
+ assert d[42] == 42
+ # Nothing to copy out (not an assignment)
+ _anon2()
+ assert "d" not in locals()
+
+However, as noted in the abstract, an actual implementation of
+this idea has never been tried.
+
+
+Reference implementation
+========================
+
+None as yet. If you want a crash course in Python namespace
+semantics and code compilation, feel free to try ;)
+
+
+References
+==========
+
+.. [1] http://mail.python.org/pipermail/python-ideas/2010-June/007476.html
+
+.. [2] http://mail.python.org/pipermail/python-ideas/2010-July/007584.html
+
+
+Copyright
+=========
+
+This document has been placed in the public domain.
+
+
+
+..
+ Local Variables:
+ mode: indented-text
+ indent-tabs-mode: nil
+ sentence-end-double-space: t
+ fill-column: 70
+ coding: utf-8
+ End:
Modified: peps/trunk/pep0/pep.py
==============================================================================
--- peps/trunk/pep0/pep.py (original)
+++ peps/trunk/pep0/pep.py Tue Jul 20 15:17:13 2010
@@ -99,7 +99,8 @@
if part[0].isupper():
break
else:
- raise ValueError("last name missing a capital letter")
+ raise ValueError("last name missing a capital letter: %r"
+ % name_parts)
base = u' '.join(name_parts[index:]).lower()
return unicodedata.normalize('NFKD', base).encode('ASCII', 'ignore')
More information about the Python-checkins
mailing list