[Python-checkins] python/nondist/peps pep-0340.txt,1.15,1.16

gvanrossum@users.sourceforge.net gvanrossum at users.sourceforge.net
Tue May 3 18:32:27 CEST 2005


Update of /cvsroot/python/python/nondist/peps
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16785

Modified Files:
	pep-0340.txt 
Log Message:
Solidify loose ends.


Index: pep-0340.txt
===================================================================
RCS file: /cvsroot/python/python/nondist/peps/pep-0340.txt,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- pep-0340.txt	2 May 2005 23:35:52 -0000	1.15
+++ pep-0340.txt	3 May 2005 16:32:24 -0000	1.16
@@ -22,10 +22,6 @@
     (Reliable Acquisition/Release Pairs), and PEP 325
     (Resource-Release Support for Generators).
 
-    This proposal is just a strawman; we've had a heated debate about
-    this on python-dev recently [1], and I figured it would be time to
-    write up a precise spec in PEP form.
-
 Motivation and Summary
 
     (Thanks to Shane Hathaway -- Hi Shane!)
@@ -70,7 +66,7 @@
 
 Use Cases
 
-    TBD.  For now, see the Examples section near the end.
+    See the Examples section near the end.
 
 Specification: the __next__() Method
 
@@ -159,14 +155,15 @@
     This is also the case in the body of the block-statement proposed
     below.
 
+    EXPR2 may contain commas; "continue 1, 2, 3" is equivalent to
+    "continue (1, 2, 3)".
+
 Specification: the Anonymous Block Statement
 
     A new statement is proposed with the syntax
 
         block EXPR1 as VAR1:
             BLOCK1
-        else:
-            BLOCK2
 
     Here, 'block' and 'as' are new keywords; EXPR1 is an arbitrary
     expression (but not an expression-list) and VAR1 is an arbitrary
@@ -268,14 +265,14 @@
     the limitations of all finalization semantics) that the block will
     be resumed eventually.
 
-    I haven't decided yet whether the block-statement should also
-    allow an optional else-clause, like the for-loop, but I'm leaning
-    against it.  I think it would be confusing, and emphasize the
+    Unlike the for-loop, the block-statement does not have an
+    else-clause.  I think it would be confusing, and emphasize the
     "loopiness" of the block-statement, while I want to emphasize its
     *difference* from a for-loop.  In addition, there are several
-    possible semantics for an else-clause.
+    possible semantics for an else-clause, and only a very weak use
+    case.
 
-Specification: Generator Exception Handling
+Specification: Generator Exit Handling
 
     Generators will implement the new __next__() method API, as well
     as the old argument-less next() method which becomes an alias for
@@ -330,11 +327,10 @@
     When __next__() is called with an argument that is not None, the
     yield-expression that it resumes will return the value attribute
     of the argument.  If it resumes a yield-statement, the value is
-    ignored (or should this be considered an error?).  When the
-    *initial* call to __next__() receives an argument that is not
-    None, the generator's execution is started normally; the
-    argument's value attribute is ignored (or should this be
-    considered an error?).  When __next__() is called without an
+    ignored (this is similar to ignoring the value returned by a
+    function call).  When the *initial* call to __next__() receives an
+    argument that is not None, TypeError is raised; this is likely
+    caused by some logic error.  When __next__() is called without an
     argument or with None as argument, and a yield-expression is
     resumed, the yield-expression returns None.
 
@@ -360,22 +356,20 @@
     cases work differently; in Python, you cannot save the block for
     later use, and you cannot test whether there is a block or not.
 
-Loose Ends
-
-    These are things that need to be resolved before accepting the
-    PEP.
+Alternatives Considered
 
-    - Fill in the remaining TBD sections.
+    - Many alternatives have been proposed for 'block', including '@'
+      and no keyword at all.  I haven't seen a proposal for another
+      keyword that I like better than 'block' yet, and not using a
+      keyword at all makes many folks (including me) uncomfortable.
 
-    - Address Phillip Eby's proposal to have the block-statement use
+    - Phillip Eby has proposed to have the block-statement use
       an entirely different API than the for-loop, to differentiate
-      between the two (a generator would have to be wrapped in a
-      decorator to make it support the block API).
-
-    - Decide on the keyword ('block', 'with', '@', nothing, or
-      something else?).
-
-    - Whether a block-statement should allow an else-clause.
+      between the two.  A generator would have to be wrapped in a
+      decorator to make it support the block API.  IMO this adds more
+      complexity with very little benefit; and we can't relly deny
+      that the block-statement is conceptually a loop -- it supports
+      break and continue, after all.
 
 Comparison to Thunks
 
@@ -418,7 +412,7 @@
     and I'd be bummed if I couldn't write this as:
 
        def findSomething(self, key, default=None):
-           block synchronized(self.lock):
+           block locking(self.lock):
                 for item in self.elements:
                     if item.matches(key):
                         return item
@@ -427,7 +421,7 @@
     This particular example can be rewritten using a break:
 
        def findSomething(self, key, default=None):
-           block synchronized(self.lock):
+           block locking(self.lock):
                 for item in self.elements:
                     if item.matches(key):
                         break
@@ -478,16 +472,17 @@
 
     However, the use cases for multiple blocks seem elusive.
 
-Alternatives Considered
-
-    TBD.
+    (Proposals have since been made to change the implementation of
+    thunks to remove most of these objections, but the resulting
+    semantics are fairly complex to explain and to implement, so IMO
+    that defeats the purpose of using thunks in the first place.)
 
 Examples
 
     1. A template for ensuring that a lock, acquired at the start of a
        block, is released when the block is left:
 
-        def synchronized(lock):
+        def locking(lock):
             lock.acquire()
             try:
                 yield
@@ -496,7 +491,7 @@
 
        Used as follows:
 
-        block synchronized(myLock):
+        block locking(myLock):
             # Code here executes with myLock held.  The lock is
             # guaranteed to be released when the block is left (even
             # if by an uncaught exception).
@@ -549,18 +544,40 @@
 
     5. It is possible to nest blocks and combine templates:
 
-        def synchronized_opening(lock, filename, mode="r"):
-            block synchronized(lock):
+        def locking_opening(lock, filename, mode="r"):
+            block locking(lock):
                 block opening(filename) as f:
                     yield f
 
        Used as follows:
 
-        block synchronized_opening("/etc/passwd", myLock) as f:
+        block locking_opening("/etc/passwd", myLock) as f:
             for line in f:
                 print line.rstrip()
 
-    6. Coroutine example TBD.
+    6. It is possible to write a regular iterator with the
+       semantics of example 1:
+
+	class locking:
+	   def __init__(self, lock):
+	       self.lock = lock
+	       self.state = 0
+	   def __next__(self, arg=None):
+	       # ignores arg
+	       if self.state:
+		   assert self.state == 1
+		   self.lock.release()
+		   self.state += 1
+		   raise StopIteration
+	       else:
+		   self.lock.acquire()
+		   self.state += 1
+		   return None
+	   def __exit__(self, type, value=None, traceback=None):
+	       assert self.state in (0, 1, 2)
+	       if self.state == 1:
+		   self.lock.release()
+	       raise type, value, traceback
 
 Acknowledgements
 



More information about the Python-checkins mailing list