[Python-checkins] peps: Switch PEP 403 from : and @ symbols to postdef and def keywords

nick.coghlan python-checkins at python.org
Thu Oct 13 13:30:20 CEST 2011


http://hg.python.org/peps/rev/b4dc86fcc359
changeset:   3965:b4dc86fcc359
user:        Nick Coghlan <ncoghlan at gmail.com>
date:        Thu Oct 13 21:30:11 2011 +1000
summary:
  Switch PEP 403 from : and @ symbols to postdef and def keywords

files:
  pep-0403.txt |  138 ++++++++++++++++++++++----------------
  1 files changed, 80 insertions(+), 58 deletions(-)


diff --git a/pep-0403.txt b/pep-0403.txt
--- a/pep-0403.txt
+++ b/pep-0403.txt
@@ -1,5 +1,5 @@
 PEP: 403
-Title: Statement local classes and functions
+Title: Prefix syntax for post function definition operations
 Version: $Revision$
 Last-Modified: $Date$
 Author: Nick Coghlan <ncoghlan at gmail.com>
@@ -15,17 +15,17 @@
 Abstract
 ========
 
-This PEP proposes the addition of ':' as a new class and function prefix
-syntax (analogous to decorators) that permits a statement local function or
-class definition to be appended to any Python statement that currently does
-not have an associated suite.
+This PEP proposes the addition of ``postdef`` as a new function prefix
+syntax (analogous to decorators) that permits the execution of a single simple
+statement (potentially including substatements separated by semi-colons) after
 
-In addition, the new syntax would allow the '@' symbol to be used to refer
-to the statement local function or class without needing to repeat the name.
+In addition, the new syntax would allow the 'def' keyword to be used to refer
+to the function being defined without needing to repeat the name.
 
-When the ':' prefix syntax is used, the associated statement would be executed
-*instead of* the normal local name binding currently implicit in function
-and class definitions.
+When the 'postdef' prefix syntax is used, the associated statement would be
+executed *in addition to* the normal local name binding implicit in function
+definitions. Any name collision are expected to be minor, analagous to those
+encountered with ``for`` loop iteration variables.
 
 This PEP is based heavily on many of the ideas in PEP 3150 (Statement Local
 Namespaces) so some elements of the rationale will be familiar to readers of
@@ -57,7 +57,7 @@
 
 As a trivial example, weakref callbacks could be defined as follows::
 
-    :x = weakref.ref(obj, @)
+    postdef x = weakref.ref(target, def)
     def report_destruction(obj):
         print("{} is being destroyed".format(obj))
 
@@ -67,33 +67,39 @@
     def report_destruction(obj):
         print("{} is being destroyed".format(obj))
 
-    x = weakref.ref(obj, report_destruction)
+    x = weakref.ref(target, report_destruction)
 
 That structure is OK when you're using the callable multiple times, but
 it's irritating to be forced into it for one-off operations.
 
-Similarly, singleton classes could now be defined as::
+Similarly, a sorted operation on a particularly poorly defined type could
+now be defined as::
 
-  :instance = @()
-  class OnlyOneInstance:
-    pass
+    postdef sorted_list = sorted(original, key=def)
+    def force_sort(item):
+        try:
+            return item.calc_sort_order()
+        except NotSortableError:
+            return float('inf')
 
 Rather than::
 
-  class OnlyOneInstance:
-    pass
+    def force_sort(item):
+        try:
+            return item.calc_sort_order()
+        except NotSortableError:
+            return float('inf')
 
-  instance = OnlyOneInstance()
+    sorted_list = sorted(original, key=force_sort)
 
-And the infamous accumulator example could become::
+And early binding semantics in a list comprehension could be attained via::
 
-    def counter():
-        x = 0
-        :return @
-        def increment():
-            nonlocal x
-            x += 1
-            return x
+    postdef funcs = [def(i) for i in range(10)]
+    def make_incrementor(i):
+        postdef return def
+        def incrementor(x):
+            return x + i
+
 
 Proposal
 ========
@@ -101,16 +107,19 @@
 This PEP proposes the addition of an optional block prefix clause to the
 syntax for function and class definitions.
 
-This block prefix would be introduced by a leading ``:`` and would be
+This block prefix would be introduced by a leading ``postdef`` and would be
 allowed to contain any simple statement (including those that don't
 make any sense in that context - while such code would be legal,
-there wouldn't be any point in writing it).
+there wouldn't be any point in writing it). This permissive structure is
+easier to define and easier to explain, but a more restrictive approach that
+only permits operations that "make sense" would also be possible (see PEP
+3150 for a list of possible candidates)
 
-The decorator symbol ``@`` would be repurposed inside the block prefix
-to refer to the function or class being defined.
+The function definition keyword ``def`` would be repurposed inside the block prefix
+to refer to the function being defined.
 
-When a block prefix is provided, it *replaces* the standard local
-name binding otherwise implicit in a class or function definition.
+When a block prefix is provided, the standard local name binding implicit
+in the function definition still takes place.
 
 
 Background
@@ -143,7 +152,7 @@
 the effectiveness of Ruby's blocks relies heavily on various conventions in
 the way functions are *defined* (specifically, Ruby's ``yield`` syntax to
 call blocks directly and the ``&arg`` mechanism to accept a block as a
-functions final argument.
+function's final argument).
 
 Since Python has relied on named functions for so long, the signatures of
 APIs that accept callbacks are far more diverse, thus requiring a solution
@@ -163,24 +172,35 @@
 
 This PEP also achieves most of the other effects described in PEP 3150
 without introducing a new brainbending kind of scope. All of the complex
-scoping rules in PEP 3150 are replaced in this PEP with the simple ``@``
-reference to the statement local function or class definition.
+scoping rules in PEP 3150 are replaced in this PEP with the simple ``def``
+reference to the associated function definition.
 
 
-Symbol Choice
+Keyword Choice
 ==============
 
-The ':' symbol was chosen due to its existing presence in Python and its
-association with 'functions in expressions' via ``lambda`` expressions. The
-past Simple Implicit Lambda proposal (PEP ???) was also a factor.
+The proposal definitely requires *some* kind of prefix to avoid parsing
+ambiguity and backwards compatibility problems with existing constructs.
+It also needs to be clearly highlighted to readers, since it declares that
+the following piece of code is going to be executed out of order.
 
-The proposal definitely requires *some* kind of prefix to avoid parsing
-ambiguity and backwards compatibility problems and ':' at least has the
-virtue of brevity. There's no obious alternative symbol that offers a
-clear improvement.
+The 'postdef' keyword was chosen as a literal explanation of exactly what
+the new clause does: execute the specified statement *after* the associated
+function definition, even though it is physically written *before* the
+definition in the source code.
 
-Introducing a new keyword is another possibility, but I haven't come up
-with one that really has anything to offer over the leading colon.
+
+Requirement to Name Functions
+=============================
+
+One of the objections to widespread use of lambda expressions is that they
+have an atrocious effect on traceback intelligibility and other aspects of
+introspection. Accordingly, this PEP requires that even throwaway functions
+be given some kind of name.
+
+To help encourage the use of meaningful names without users having to repeat
+themselves, the PEP suggests the provision of the ``def`` shorthand reference
+to the current function from the ``postdef`` clause.
 
 
 Syntax Change
@@ -198,17 +218,17 @@
     atom: ('(' [yield_expr|testlist_comp] ')' |
            '[' [testlist_comp] ']' |
            '{' [dictorsetmaker] '}' |
-           NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False' | '@')
+           NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False' | 'def')
 
 New::
 
-    blockprefix: ':' simple_stmt
-    block: blockprefix (decorated | classdef | funcdef)
+    blockprefix: 'postdef' simple_stmt
+    block: blockprefix funcdef
 
-The above is the general idea, but I suspect that change to the 'atom'
-definition would cause an ambiguity problem in the parser when it comes to
-detecting decorator lines. So the actual implementation would be more complex
-than that.
+The above is the general idea, but I suspect that the change to the 'atom'
+definition may cause an ambiguity problem in the parser when it comes to
+detecting function definitions. So the actual implementation may need to be
+more complex than that.
 
 Grammar: http://hg.python.org/cpython/file/default/Grammar/Grammar
 
@@ -219,13 +239,12 @@
 This proposal has one titanic advantage over PEP 3150: implementation
 should be relatively straightforward.
 
-Both the class and function definition statements emit code to perform
-the local name binding for their defined name. Implementing this PEP
-should just require intercepting that code generation and replacing
-it with the code in the block prefix.
+The post definition statement can be incorporated into the AST for the
+function node and simply visited out of sequence.
 
 The one potentially tricky part is working out how to allow the dual
-use of '@' without rewriting half the grammar definition.
+use of 'def' without rewriting half the grammar definition.
+
 
 More Examples
 =============
@@ -273,6 +292,9 @@
 
 Sort out links and references to everything :)
 
+Start of python-ideas thread:
+http://mail.python.org/pipermail/python-ideas/2011-October/012276.html
+
 
 Acknowledgements
 ================

-- 
Repository URL: http://hg.python.org/peps


More information about the Python-checkins mailing list