[Python-checkins] r47107 - peps/trunk/Makefile peps/trunk/pep-0000.txt peps/trunk/pep-3103.txt

guido.van.rossum python-checkins at python.org
Mon Jun 26 20:05:40 CEST 2006


Author: guido.van.rossum
Date: Mon Jun 26 20:05:39 2006
New Revision: 47107

Modified:
   peps/trunk/Makefile
   peps/trunk/pep-0000.txt
   peps/trunk/pep-3103.txt
Log:
Add PEP 3103: A Switch/Case Statement (GvR).
Also fix a reference to cvs in the Makefile.


Modified: peps/trunk/Makefile
==============================================================================
--- peps/trunk/Makefile	(original)
+++ peps/trunk/Makefile	Mon Jun 26 20:05:39 2006
@@ -23,4 +23,4 @@
 	-rm *.html
 
 update:
-	cvs update -P -d
+	svn update

Modified: peps/trunk/pep-0000.txt
==============================================================================
--- peps/trunk/pep-0000.txt	(original)
+++ peps/trunk/pep-0000.txt	Mon Jun 26 20:05:39 2006
@@ -99,6 +99,7 @@
  S   754  IEEE 754 Floating Point Special Values       Warnes
  S  3101  Advanced String Formatting                   Talin
  S  3102  Keyword-Only Arguments                       Talin
+ S  3103  A Switch/Case Statement                      GvR
 
  Finished PEPs (done, implemented in Subversion)
 
@@ -431,6 +432,7 @@
  I  3100  Python 3.0 Plans                             Kuchling, Cannon
  S  3101  Advanced String Formatting                   Talin
  S  3102  Keyword-Only Arguments                       Talin
+ S  3103  A Switch/Case Statement                      GvR
 
 Key
 

Modified: peps/trunk/pep-3103.txt
==============================================================================
--- peps/trunk/pep-3103.txt	(original)
+++ peps/trunk/pep-3103.txt	Mon Jun 26 20:05:39 2006
@@ -8,7 +8,7 @@
 Python-Version: 3.0
 Content-Type: text/x-rst
 Created: 25-Jun-2006
-Post-History: never
+Post-History: 26-Jun-2006
 
 
 Abstract
@@ -24,6 +24,11 @@
 somewhat different from that PEP's author, but I'm grateful for the
 work done in that PEP.
 
+This PEP introduces canonical names for the many variants that have
+been discussed for different aspects of the syntax and semantics, such
+as "alternative 2", "school II", "Option 3" and so on.  Hopefully
+these names will help the discussion.
+
 
 Rationale
 =========
@@ -216,10 +221,10 @@
 
     case [*]EXPR, [*]EXPR, ...:
 
-Note that the * notation is similar to the use of prefix * already in
-use for variable-length parameter lists and for passing computed
-argument lists, and often proposed for value-unpacking (e.g.  "a, b,
-*c = X" as an alternative to "(a, b), c = X[:2], X[2:]").
+The * notation is similar to the use of prefix * already in use for
+variable-length parameter lists and for passing computed argument
+lists, and often proposed for value-unpacking (e.g.  "a, b, *c = X" as
+an alternative to "(a, b), c = X[:2], X[2:]").
 
 Alternative D
 -------------
@@ -390,16 +395,17 @@
 Assuming the switch will be executed many times, doing some extra work
 the first time pays back quickly by very quick dispatch times later.
 
-A mostly theoretical objection to this option is that there is no
-obvious object where the dispatch dict can be stored.  It can't be
-stored on the code object, which is supposed to be immutable; it can't
-be stored on the function object, since many function objects may be
-created for the same function (e.g. for nested functions).  In
-practice, I'm sure that something can be found; it could be stored in
-a section of the code object that's not considered when comparing two
-code objects or when pickling or marshalling a code object; or all
-switches could be stored in a dict indexed by weak references to code
-objects.
+An objection to this option is that there is no obvious object where
+the dispatch dict can be stored.  It can't be stored on the code
+object, which is supposed to be immutable; it can't be stored on the
+function object, since many function objects may be created for the
+same function (e.g. for nested functions).  In practice, I'm sure that
+something can be found; it could be stored in a section of the code
+object that's not considered when comparing two code objects or when
+pickling or marshalling a code object; or all switches could be stored
+in a dict indexed by weak references to code objects.  The solution
+should also be careful not to leak switch dicts between multiple
+interpreters.
 
 Another objection is that the first-use rule allows obfuscated code
 like this::
@@ -419,17 +425,101 @@
 but that's not what it does (unless it is always called with the same
 value as the second argument).  This has been addressed by suggesting
 that the case expressions should not be allowed to reference local
-variables.  But this is somewhat arbitrary.
+variables, but this is somewhat arbitrary.
 
 A final objection is that in a multi-threaded application, the
 first-use rule requires intricate locking in order to guarantee the
 correct semantics.  (The first-use rule suggests a promise that side
-effects of case expressions are incurred exactly once.)
+effects of case expressions are incurred exactly once.)  This may be
+as tricky as the import lock has proved to be, since the lock has to
+be held while all the case expressions are being evaluated.
 
 Option 3
 ''''''''
 
-TBD
+A proposal that has been winning support (including mine) is to freeze
+a switch's dict when the innermost function containing it is defined.
+The switch dict is stored on the function object, just as parameter
+defaults are, and in fact the case expressions are evaluated at the
+same time and in the same scope as the parameter defaults (i.e. in the
+scope containing the function definition).
+
+This option has the advantage of avoiding many of the finesses needed
+to make option 2 work: there's no need for locking, no worry about
+immutable code objects or multiple interpreters.  It also provides a
+clear explanation for why locals can't be referenced in case
+expressions.
+
+This option works just as well for situations where one would
+typically use a switch; case expressions involving imported or global
+named constants work exactly the same way as in option 2, as long as
+they are imported or defined before the function definition is
+encountered.
+
+A downside however is that the dispatch dict for a switch inside a
+nested function must be recomputed each time the nested function is
+defined.  For certain "functional" styles of programming this may make
+switch unattractive in nested functions.  (Unless all case expressions
+are compile-time constants; then the compiler is of course free to
+optimize away the swich freezing code and make the dispatch table part
+of the code object.)
+
+Another downside is that under this option, there's no clear moment
+when the dispatch dict is frozen for a switch that doesn't occur
+inside a function.  There are a few pragmatic choices for how to treat
+a switch outside a function:
+
+  (a) Disallow it.
+  (b) Translate it into an if/elif chain.
+  (c) Allow only compile-time constant expressions.
+  (d) Compute the dispatch dict each time the switch is reached.
+  (e) Like (b) but tests that all expressions evaluated are hashable.
+
+Of these, (a) seems too restrictive: it's uniformly worse than (c);
+and (d) has poor performance for little or no benefits compared to
+(b).  It doesn't make sense to have a performance-critical inner loop
+at the module level, as all local variable references are slow there;
+hence (b) is my (weak) favorite.  Perhaps I should favor (e), which
+attempts to prevent atypical use of a switch; examples that work
+interactively but not in a function are annoying.  In the end I don't
+think this issue is all that important (except it must be resolved
+somehow) and am willing to leave it up to whoever ends up implementing
+it.
+
+When a switch occurs in a class but not in a function, we can freeze
+the dispatch dict at the same time the temporary function object
+representing the class body is created.  This means the case
+expressions can reference module globals but not class variables.
+Alternatively, if we choose (b) above, we could choose this
+implementation inside a class definition as well.
+
+Option 4
+''''''''
+
+There are a number of proposals to add a construct to the language
+that makes the concept of a value pre-computed at function definition
+time generally available, without tying it either to parameter default
+values or case expressions.  Some keywords proposed include 'const',
+'static', 'only' or 'cached'.  The associated syntax and semantics
+vary.
+
+These proposals are out of scope for this PEP, except to suggest that
+*if* such a proposal is accepted, there are two ways for the switch to
+benefit: we could require case expressions to be either compile-time
+constants or pre-computed values; or we could make pre-computed values
+the default (and only) evaluation mode for case expressions.  The
+latter would be my preference, since I don't see a use for more
+dynamic case expressions that isn't addressed adequately by writing an
+explicit if/elif chain.
+
+
+Conclusion
+==========
+
+It is too early to decide.  I'd like to see at least one completed
+proposal for pre-computed values before deciding.  In the mean time,
+Python is fine without a switch statement, and perhaps those who claim
+it would be a mistake to add one are right.
 
 
 Copyright


More information about the Python-checkins mailing list