diff --git a/pep-0212.txt b/pep-0212.txt index 87711f052..bd5887bcf 100644 --- a/pep-0212.txt +++ b/pep-0212.txt @@ -5,163 +5,180 @@ Last-Modified: $Date$ Author: nowonder@nowonder.de (Peter Schneider-Kamp) Status: Deferred Type: Standards Track +Content-Type: text/x-rst Created: 22-Aug-2000 Python-Version: 2.1 Post-History: Introduction +============ - This PEP describes the often proposed feature of exposing the loop - counter in for-loops. This PEP tracks the status and ownership of - this feature. It contains a description of the feature and - outlines changes necessary to support the feature. This PEP - summarizes discussions held in mailing list forums, and provides - URLs for further information, where appropriate. The CVS revision - history of this file contains the definitive historical record. +This PEP describes the often proposed feature of exposing the loop +counter in for-loops. This PEP tracks the status and ownership of +this feature. It contains a description of the feature and +outlines changes necessary to support the feature. This PEP +summarizes discussions held in mailing list forums, and provides +URLs for further information, where appropriate. The CVS revision +history of this file contains the definitive historical record. Motivation +========== - Standard for-loops in Python iterate over the elements of a - sequence[1]. Often it is desirable to loop over the indices or - both the elements and the indices instead. +Standard for-loops in Python iterate over the elements of a +sequence [1]_. Often it is desirable to loop over the indices or +both the elements and the indices instead. - The common idioms used to accomplish this are unintuitive. This - PEP proposes two different ways of exposing the indices. +The common idioms used to accomplish this are unintuitive. This +PEP proposes two different ways of exposing the indices. Loop counter iteration +====================== - The current idiom for looping over the indices makes use of the - built-in 'range' function: +The current idiom for looping over the indices makes use of the +built-in ``range`` function:: - for i in range(len(sequence)): - # work with index i + for i in range(len(sequence)): + # work with index i - Looping over both elements and indices can be achieved either by the - old idiom or by using the new 'zip' built-in function[2]: +Looping over both elements and indices can be achieved either by the +old idiom or by using the new ``zip`` built-in function [2]_:: - for i in range(len(sequence)): - e = sequence[i] - # work with index i and element e + for i in range(len(sequence)): + e = sequence[i] + # work with index i and element e - or +or:: - for i, e in zip(range(len(sequence)), sequence): - # work with index i and element e + for i, e in zip(range(len(sequence)), sequence): + # work with index i and element e The Proposed Solutions +====================== - There are three solutions that have been discussed. One adds a - non-reserved keyword, the other adds two built-in functions. - A third solution adds methods to sequence objects. +There are three solutions that have been discussed. One adds a +non-reserved keyword, the other adds two built-in functions. +A third solution adds methods to sequence objects. -Non-reserved keyword 'indexing' +Non-reserved keyword ``indexing`` +================================= - This solution would extend the syntax of the for-loop by adding - an optional ' indexing' clause which can also be used - instead of the ' in' clause.. +This solution would extend the syntax of the for-loop by adding +an optional `` indexing`` clause which can also be used +instead of the `` in`` clause. - Looping over the indices of a sequence would thus become: +Looping over the indices of a sequence would thus become:: - for i indexing sequence: - # work with index i + for i indexing sequence: + # work with index i - Looping over both indices and elements would similarly be: +Looping over both indices and elements would similarly be:: - for i indexing e in sequence: - # work with index i and element e + for i indexing e in sequence: + # work with index i and element e -Built-in functions 'indices' and 'irange' +Built-in functions ``indices`` and ``irange`` +============================================= - This solution adds two built-in functions 'indices' and 'irange'. - The semantics of these can be described as follows: +This solution adds two built-in functions ``indices`` and ``irange``. +The semantics of these can be described as follows:: - def indices(sequence): - return range(len(sequence)) + def indices(sequence): + return range(len(sequence)) - def irange(sequence): - return zip(range(len(sequence)), sequence) + def irange(sequence): + return zip(range(len(sequence)), sequence) - These functions could be implemented either eagerly or lazily and - should be easy to extend in order to accept more than one sequence - argument. +These functions could be implemented either eagerly or lazily and +should be easy to extend in order to accept more than one sequence +argument. - The use of these functions would simplify the idioms for looping - over the indices and over both elements and indices: +The use of these functions would simplify the idioms for looping +over the indices and over both elements and indices:: - for i in indices(sequence): - # work with index i + for i in indices(sequence): + # work with index i - for i, e in irange(sequence): - # work with index i and element e + for i, e in irange(sequence): + # work with index i and element e Methods for sequence objects +============================ - This solution proposes the addition of 'indices', 'items' - and 'values' methods to sequences, which enable looping over - indices only, both indices and elements, and elements only - respectively. +This solution proposes the addition of ``indices``, ``items`` +and ``values`` methods to sequences, which enable looping over +indices only, both indices and elements, and elements only +respectively. - This would immensely simplify the idioms for looping over indices - and for looping over both elements and indices: +This would immensely simplify the idioms for looping over indices +and for looping over both elements and indices:: - for i in sequence.indices(): - # work with index i + for i in sequence.indices(): + # work with index i - for i, e in sequence.items(): - # work with index i and element e + for i, e in sequence.items(): + # work with index i and element e - Additionally it would allow to do looping over the elements - of sequences and dicitionaries in a consistent way: +Additionally it would allow to do looping over the elements +of sequences and dictionaries in a consistent way:: - for e in sequence_or_dict.values(): - # do something with element e + for e in sequence_or_dict.values(): + # do something with element e Implementations +=============== - For all three solutions some more or less rough patches exist - as patches at SourceForge: +For all three solutions some more or less rough patches exist +as patches at SourceForge: - 'for i indexing a in l': exposing the for-loop counter[3] - add indices() and irange() to built-ins[4] - add items() method to listobject[5] +- ``for i indexing a in l``: exposing the for-loop counter [3]_ +- add ``indices()`` and ``irange()`` to built-ins [4]_ +- add ``items()`` method to listobject [5]_ - All of them have been pronounced on and rejected by the BDFL. +All of them have been pronounced on and rejected by the BDFL. - Note that the 'indexing' keyword is only a NAME in the - grammar and so does not hinder the general use of 'indexing'. +Note that the ``indexing`` keyword is only a ``NAME`` in the +grammar and so does not hinder the general use of ``indexing``. Backward Compatibility Issues +============================= - As no keywords are added and the semantics of existing code - remains unchanged, all three solutions can be implemented - without breaking existing code. +As no keywords are added and the semantics of existing code +remains unchanged, all three solutions can be implemented +without breaking existing code. Copyright +========= - This document has been placed in the public domain. +This document has been placed in the public domain. References +========== - [1] http://docs.python.org/reference/compound_stmts.html#for - [2] Lockstep Iteration, PEP 201 - [3] http://sourceforge.net/patch/download.php?id=101138 - [4] http://sourceforge.net/patch/download.php?id=101129 - [5] http://sourceforge.net/patch/download.php?id=101178 +.. [1] http://docs.python.org/reference/compound_stmts.html#for + +.. [2] Lockstep Iteration, PEP 201 + +.. [3] http://sourceforge.net/patch/download.php?id=101138 + +.. [4] http://sourceforge.net/patch/download.php?id=101129 + +.. [5] http://sourceforge.net/patch/download.php?id=101178 - -Local Variables: -mode: indented-text -indent-tabs-mode: nil -End: + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + End: diff --git a/pep-0216.txt b/pep-0216.txt index 948bb4c88..d6acfd488 100644 --- a/pep-0216.txt +++ b/pep-0216.txt @@ -5,139 +5,164 @@ Last-Modified: $Date$ Author: moshez@zadka.site.co.il (Moshe Zadka) Status: Rejected Type: Informational +Content-Type: text/x-rst Created: 31-Jul-2000 Post-History: Superseded-By: 287 -Notice - This PEP is rejected by the author. It has been superseded by PEP - 287. +Notice +====== + +This PEP is rejected by the author. It has been superseded by PEP +287. + Abstract +======== - Named Python objects, such as modules, classes and functions, have a - string attribute called __doc__. If the first expression inside - the definition is a literal string, that string is assigned - to the __doc__ attribute. +Named Python objects, such as modules, classes and functions, have a +string attribute called ``__doc__``. If the first expression inside +the definition is a literal string, that string is assigned +to the ``__doc__`` attribute. + +The ``__doc__`` attribute is called a documentation string, or docstring. +It is often used to summarize the interface of the module, class or +function. However, since there is no common format for documentation +string, tools for extracting docstrings and transforming those into +documentation in a standard format (e.g., DocBook) have not sprang +up in abundance, and those that do exist are for the most part +unmaintained and unused. - The __doc__ attribute is called a documentation string, or docstring. - It is often used to summarize the interface of the module, class or - function. However, since there is no common format for documentation - string, tools for extracting docstrings and transforming those into - documentation in a standard format (e.g., DocBook) have not sprang - up in abundance, and those that do exist are for the most part - unmaintained and unused. Perl Documentation +================== + +In Perl, most modules are documented in a format called POD -- Plain +Old Documentation. This is an easy-to-type, very low level format +which integrates well with the Perl parser. Many tools exist to turn +POD documentation into other formats: info, HTML and man pages, among +others. However, in Perl, the information is not available at run-time. - In Perl, most modules are documented in a format called POD -- Plain - Old Documentation. This is an easy-to-type, very low level format - which integrates well with the Perl parser. Many tools exist to turn - POD documentation into other formats: info, HTML and man pages, among - others. However, in Perl, the information is not available at run-time. Java Documentation +================== + +In Java, special comments before classes and functions function to +document the code. A program to extract these, and turn them into +HTML documentation is called javadoc, and is part of the standard +Java distribution. However, the only output format that is supported +is HTML, and JavaDoc has a very intimate relationship with HTML. - In Java, special comments before classes and functions function to - document the code. A program to extract these, and turn them into - HTML documentation is called javadoc, and is part of the standard - Java distribution. However, the only output format that is supported - is HTML, and JavaDoc has a very intimate relationship with HTML. Python Docstring Goals +====================== + +Python documentation string are easy to spot during parsing, and are +also available to the runtime interpreter. This double purpose is +a bit problematic, sometimes: for example, some are reluctant to have +too long docstrings, because they do not want to take much space in +the runtime. In addition, because of the current lack of tools, people +read objects' docstrings by "print"ing them, so a tendency to make them +brief and free of markups has sprung up. This tendency hinders writing +better documentation-extraction tools, since it causes docstrings to +contain little information, which is hard to parse. - Python documentation string are easy to spot during parsing, and are - also available to the runtime interpreter. This double purpose is - a bit problematic, sometimes: for example, some are reluctant to have - too long docstrings, because they do not want to take much space in - the runtime. In addition, because of the current lack of tools, people - read objects' docstrings by "print"ing them, so a tendency to make them - brief and free of markups has sprung up. This tendency hinders writing - better documentation-extraction tools, since it causes docstrings to - contain little information, which is hard to parse. High Level Solutions +==================== + +To counter the objection that the strings take up place in the running +program, it is suggested that documentation extraction tools will +concatenate a maximum prefix of string literals which appear in the +beginning of a definition. The first of these will also be available +in the interactive interpreter, so it should contain a few summary +lines. - To counter the objection that the strings take up place in the running - program, it is suggested that documentation extraction tools will - concatenate a maximum prefix of string literals which appear in the - beginning of a definition. The first of these will also be available - in the interactive interpreter, so it should contain a few summary - lines. Docstring Format Goals +====================== - These are the goals for the docstring format, as discussed ad neasum - in the doc-sig. +These are the goals for the docstring format, as discussed ad nauseam +in the doc-sig. + +1. It must be easy to type with any standard text editor. +2. It must be readable to the casual observer. +3. It must not contain information which can be deduced from parsing + the module. +4. It must contain sufficient information so it can be converted + to any reasonable markup format. +5. It must be possible to write a module's entire documentation in + docstrings, without feeling hampered by the markup language. - 1. It must be easy to type with any standard text editor. - 2. It must be readable to the casual observer. - 3. It must not contain information which can be deduced from parsing - the module. - 4. It must contain sufficient information so it can be converted - to any reasonable markup format. - 5. It must be possible to write a module's entire documentation in - docstrings, without feeling hampered by the markup language. Docstring Contents +================== - For requirement 5. above, it is needed to specify what must be - in docstrings. +For requirement 5. above, it is needed to specify what must be +in docstrings. - At least the following must be available: +At least the following must be available: - a. A tag that means "this is a Python ``something'', guess what" +a. A tag that means "this is a Python `something`, guess what" - Example: In the sentence "The POP3 class", we need to markup "POP3" - so. The parser will be able to guess it is a class from the contents - of the poplib module, but we need to make it guess. + Example: In the sentence "The POP3 class", we need to markup "POP3" + so. The parser will be able to guess it is a class from the contents + of the ``poplib`` module, but we need to make it guess. - b. Tags that mean "this is a Python class/module/class var/instance var..." +b. Tags that mean "this is a Python class/module/class var/instance var..." - Example: The usual Python idiom for singleton class A is to have _A - as the class, and A a function which returns _A objects. It's usual - to document the class, nonetheless, as being A. This requires the - strength to say "The class A" and have A hyperlinked and marked-up - as a class. + Example: The usual Python idiom for singleton class ``A`` is to have ``_A`` + as the class, and ``A`` a function which returns ``_A`` objects. It's usual + to document the class, nonetheless, as being ``A``. This requires the + strength to say "The class ``A``" and have ``A`` hyperlinked and marked-up + as a class. + +c. An easy way to include Python source code/Python interactive sessions + +d. Emphasis/bold + +e. List/tables - c. An easy way to include Python source code/Python interactive sessions - d. Emphasis/bold - e. List/tables Docstring Basic Structure +========================= + +The documentation strings will be in StructuredTextNG +(http://www.zope.org/Members/jim/StructuredTextWiki/StructuredTextNG) +Since StructuredText is not yet strong enough to handle (a) and (b) +above, we will need to extend it. I suggest using +``[:python identifier]``. +E.g.: ``[class:POP3]``, ``[:POP3.list]``, etc. If the description is missing, +a guess will be made from the text. - The documentation strings will be in StructuredTextNG - (http://www.zope.org/Members/jim/StructuredTextWiki/StructuredTextNG) - Since StructuredText is not yet strong enough to handle (a) and (b) - above, we will need to extend it. I suggest using - '[:python identifier]'. - E.g.: [class:POP3], [:POP3.list], etc. If the description is missing, - a guess will be made from the text. Unresolved Issues - - Is there a way to escape characters in ST? If so, how? - (example: * at the beginning of a line without being bullet symbol) +================= - Is my suggestion above for Python symbols compatible with ST-NG? - How hard would it be to extend ST-NG to support it? +Is there a way to escape characters in ST? If so, how? +(example: * at the beginning of a line without being bullet symbol) - How do we describe input and output types of functions? +Is my suggestion above for Python symbols compatible with ST-NG? +How hard would it be to extend ST-NG to support it? - What additional constraint do we enforce on each docstring? - (module/class/function)? +How do we describe input and output types of functions? + +What additional constraint do we enforce on each docstring? +(module/class/function)? + +What are the guesser rules? - What are the guesser rules? Rejected Suggestions +==================== - XML -- it's very hard to type, and too cluttered to read it - comfortably. +XML -- it's very hard to type, and too cluttered to read it comfortably. - -Local Variables: -mode: indented-text -indent-tabs-mode: nil -End: + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + End: diff --git a/pep-0219.txt b/pep-0219.txt index 0206ff104..039eba372 100644 --- a/pep-0219.txt +++ b/pep-0219.txt @@ -5,187 +5,195 @@ Last-Modified: $Date$ Author: gmcm@hypernet.com (Gordon McMillan) Status: Deferred Type: Standards Track +Content-Type: text/x-rst Created: 14-Aug-2000 Python-Version: 2.1 Post-History: Introduction +============ - This PEP discusses changes required to core Python in order to - efficiently support generators, microthreads and coroutines. It is - related to PEP 220, which describes how Python should be extended - to support these facilities. The focus of this PEP is strictly on - the changes required to allow these extensions to work. +This PEP discusses changes required to core Python in order to +efficiently support generators, microthreads and coroutines. It is +related to PEP 220, which describes how Python should be extended +to support these facilities. The focus of this PEP is strictly on +the changes required to allow these extensions to work. - While these PEPs are based on Christian Tismer's Stackless[1] - implementation, they do not regard Stackless as a reference - implementation. Stackless (with an extension module) implements - continuations, and from continuations one can implement - coroutines, microthreads (as has been done by Will Ware[2]) and - generators. But in more that a year, no one has found any other - productive use of continuations, so there seems to be no demand - for their support. +While these PEPs are based on Christian Tismer's Stackless [1]_ +implementation, they do not regard Stackless as a reference +implementation. Stackless (with an extension module) implements +continuations, and from continuations one can implement +coroutines, microthreads (as has been done by Will Ware [2]_) and +generators. But in more that a year, no one has found any other +productive use of continuations, so there seems to be no demand +for their support. - However, Stackless support for continuations is a relatively minor - piece of the implementation, so one might regard it as "a" - reference implementation (rather than "the" reference - implementation). +However, Stackless support for continuations is a relatively minor +piece of the implementation, so one might regard it as "a" +reference implementation (rather than "the" reference +implementation). Background +========== - Generators and coroutines have been implemented in a number of - languages in a number of ways. Indeed, Tim Peters has done pure - Python implementations of generators[3] and coroutines[4] using - threads (and a thread-based coroutine implementation exists for - Java). However, the horrendous overhead of a thread-based - implementation severely limits the usefulness of this approach. +Generators and coroutines have been implemented in a number of +languages in a number of ways. Indeed, Tim Peters has done pure +Python implementations of generators [3]_ and coroutines [4]_ using +threads (and a thread-based coroutine implementation exists for +Java). However, the horrendous overhead of a thread-based +implementation severely limits the usefulness of this approach. - Microthreads (a.k.a "green" or "user" threads) and coroutines - involve transfers of control that are difficult to accommodate in - a language implementation based on a single stack. (Generators can - be done on a single stack, but they can also be regarded as a very - simple case of coroutines.) +Microthreads (a.k.a "green" or "user" threads) and coroutines +involve transfers of control that are difficult to accommodate in +a language implementation based on a single stack. (Generators can +be done on a single stack, but they can also be regarded as a very +simple case of coroutines.) - Real threads allocate a full-sized stack for each thread of - control, and this is the major source of overhead. However, - coroutines and microthreads can be implemented in Python in a way - that involves almost no overhead. This PEP, therefor, offers a - way for making Python able to realistically manage thousands of - separate "threads" of activity (vs. today's limit of perhaps dozens - of separate threads of activity). +Real threads allocate a full-sized stack for each thread of +control, and this is the major source of overhead. However, +coroutines and microthreads can be implemented in Python in a way +that involves almost no overhead. This PEP, therefor, offers a +way for making Python able to realistically manage thousands of +separate "threads" of activity (vs. today's limit of perhaps dozens +of separate threads of activity). - Another justification for this PEP (explored in PEP 220) is that - coroutines and generators often allow a more direct expression of - an algorithm than is possible in today's Python. +Another justification for this PEP (explored in PEP 220) is that +coroutines and generators often allow a more direct expression of +an algorithm than is possible in today's Python. Discussion +========== - The first thing to note is that Python, while it mingles - interpreter data (normal C stack usage) with Python data (the - state of the interpreted program) on the stack, the two are - logically separate. They just happen to use the same stack. +The first thing to note is that Python, while it mingles +interpreter data (normal C stack usage) with Python data (the +state of the interpreted program) on the stack, the two are +logically separate. They just happen to use the same stack. - A real thread gets something approaching a process-sized stack - because the implementation has no way of knowing how much stack - space the thread will require. The stack space required for an - individual frame is likely to be reasonable, but stack switching - is an arcane and non-portable process, not supported by C. +A real thread gets something approaching a process-sized stack +because the implementation has no way of knowing how much stack +space the thread will require. The stack space required for an +individual frame is likely to be reasonable, but stack switching +is an arcane and non-portable process, not supported by C. - Once Python stops putting Python data on the C stack, however, - stack switching becomes easy. +Once Python stops putting Python data on the C stack, however, +stack switching becomes easy. - The fundamental approach of the PEP is based on these two - ideas. First, separate C's stack usage from Python's stack - usage. Secondly, associate with each frame enough stack space to - handle that frame's execution. +The fundamental approach of the PEP is based on these two +ideas. First, separate C's stack usage from Python's stack +usage. Secondly, associate with each frame enough stack space to +handle that frame's execution. - In the normal usage, Stackless Python has a normal stack - structure, except that it is broken into chunks. But in the - presence of a coroutine / microthread extension, this same - mechanism supports a stack with a tree structure. That is, an - extension can support transfers of control between frames outside - the normal "call / return" path. +In the normal usage, Stackless Python has a normal stack +structure, except that it is broken into chunks. But in the +presence of a coroutine / microthread extension, this same +mechanism supports a stack with a tree structure. That is, an +extension can support transfers of control between frames outside +the normal "call / return" path. Problems +======== - The major difficulty with this approach is C calling Python. The - problem is that the C stack now holds a nested execution of the - byte-code interpreter. In that situation, a coroutine / - microthread extension cannot be permitted to transfer control to a - frame in a different invocation of the byte-code interpreter. If a - frame were to complete and exit back to C from the wrong - interpreter, the C stack could be trashed. +The major difficulty with this approach is C calling Python. The +problem is that the C stack now holds a nested execution of the +byte-code interpreter. In that situation, a coroutine / +microthread extension cannot be permitted to transfer control to a +frame in a different invocation of the byte-code interpreter. If a +frame were to complete and exit back to C from the wrong +interpreter, the C stack could be trashed. - The ideal solution is to create a mechanism where nested - executions of the byte code interpreter are never needed. The easy - solution is for the coroutine / microthread extension(s) to - recognize the situation and refuse to allow transfers outside the - current invocation. +The ideal solution is to create a mechanism where nested +executions of the byte code interpreter are never needed. The easy +solution is for the coroutine / microthread extension(s) to +recognize the situation and refuse to allow transfers outside the +current invocation. - We can categorize code that involves C calling Python into two - camps: Python's implementation, and C extensions. And hopefully we - can offer a compromise: Python's internal usage (and C extension - writers who want to go to the effort) will no longer use a nested - invocation of the interpreter. Extensions which do not go to the - effort will still be safe, but will not play well with coroutines - / microthreads. +We can categorize code that involves C calling Python into two +camps: Python's implementation, and C extensions. And hopefully we +can offer a compromise: Python's internal usage (and C extension +writers who want to go to the effort) will no longer use a nested +invocation of the interpreter. Extensions which do not go to the +effort will still be safe, but will not play well with coroutines +/ microthreads. - Generally, when a recursive call is transformed into a loop, a bit - of extra bookkeeping is required. The loop will need to keep its - own "stack" of arguments and results since the real stack can now - only hold the most recent. The code will be more verbose, because - it's not quite as obvious when we're done. While Stackless is not - implemented this way, it has to deal with the same issues. +Generally, when a recursive call is transformed into a loop, a bit +of extra bookkeeping is required. The loop will need to keep its +own "stack" of arguments and results since the real stack can now +only hold the most recent. The code will be more verbose, because +it's not quite as obvious when we're done. While Stackless is not +implemented this way, it has to deal with the same issues. - In normal Python, PyEval_EvalCode is used to build a frame and - execute it. Stackless Python introduces the concept of a - FrameDispatcher. Like PyEval_EvalCode, it executes one frame. But - the interpreter may signal the FrameDispatcher that a new frame - has been swapped in, and the new frame should be executed. When a - frame completes, the FrameDispatcher follows the back pointer to - resume the "calling" frame. +In normal Python, ``PyEval_EvalCode`` is used to build a frame and +execute it. Stackless Python introduces the concept of a +``FrameDispatcher``. Like ``PyEval_EvalCode``, it executes one frame. But +the interpreter may signal the ``FrameDispatcher`` that a new frame +has been swapped in, and the new frame should be executed. When a +frame completes, the ``FrameDispatcher`` follows the back pointer to +resume the "calling" frame. - So Stackless transforms recursions into a loop, but it is not the - FrameDispatcher that manages the frames. This is done by the - interpreter (or an extension that knows what it's doing). +So Stackless transforms recursions into a loop, but it is not the +``FrameDispatcher`` that manages the frames. This is done by the +interpreter (or an extension that knows what it's doing). - The general idea is that where C code needs to execute Python - code, it creates a frame for the Python code, setting its back - pointer to the current frame. Then it swaps in the frame, signals - the FrameDispatcher and gets out of the way. The C stack is now - clean - the Python code can transfer control to any other frame - (if an extension gives it the means to do so). +The general idea is that where C code needs to execute Python +code, it creates a frame for the Python code, setting its back +pointer to the current frame. Then it swaps in the frame, signals +the ``FrameDispatcher`` and gets out of the way. The C stack is now +clean - the Python code can transfer control to any other frame +(if an extension gives it the means to do so). - In the vanilla case, this magic can be hidden from the programmer - (even, in most cases, from the Python-internals programmer). Many - situations present another level of difficulty, however. +In the vanilla case, this magic can be hidden from the programmer +(even, in most cases, from the Python-internals programmer). Many +situations present another level of difficulty, however. - The map builtin function involves two obstacles to this - approach. It cannot simply construct a frame and get out of the - way, not just because there's a loop involved, but each pass - through the loop requires some "post" processing. In order to play - well with others, Stackless constructs a frame object for map - itself. +The map builtin function involves two obstacles to this +approach. It cannot simply construct a frame and get out of the +way, not just because there's a loop involved, but each pass +through the loop requires some "post" processing. In order to play +well with others, Stackless constructs a frame object for map +itself. + +Most recursions of the interpreter are not this complex, but +fairly frequently, some "post" operations are required. Stackless +does not fix these situations because of amount of code changes +required. Instead, Stackless prohibits transfers out of a nested +interpreter. While not ideal (and sometimes puzzling), this +limitation is hardly crippling. - Most recursions of the interpreter are not this complex, but - fairly frequently, some "post" operations are required. Stackless - does not fix these situations because of amount of code changes - required. Instead, Stackless prohibits transfers out of a nested - interpreter. While not ideal (and sometimes puzzling), this - limitation is hardly crippling. - Advantages +========== - For normal Python, the advantage to this approach is that C stack - usage becomes much smaller and more predictable. Unbounded - recursion in Python code becomes a memory error, instead of a - stack error (and thus, in non-Cupertino operating systems, - something that can be recovered from). The price, of course, is - the added complexity that comes from transforming recursions of - the byte-code interpreter loop into a higher order loop (and the - attendant bookkeeping involved). +For normal Python, the advantage to this approach is that C stack +usage becomes much smaller and more predictable. Unbounded +recursion in Python code becomes a memory error, instead of a +stack error (and thus, in non-Cupertino operating systems, +something that can be recovered from). The price, of course, is +the added complexity that comes from transforming recursions of +the byte-code interpreter loop into a higher order loop (and the +attendant bookkeeping involved). - The big advantage comes from realizing that the Python stack is - really a tree, and the frame dispatcher can transfer control - freely between leaf nodes of the tree, thus allowing things like - microthreads and coroutines. +The big advantage comes from realizing that the Python stack is +really a tree, and the frame dispatcher can transfer control +freely between leaf nodes of the tree, thus allowing things like +microthreads and coroutines. References +========== - [1] http://www.stackless.com - [2] http://world.std.com/~wware/uthread.html - [3] Demo/threads/Generator.py in the source distribution - [4] http://www.stackless.com/coroutines.tim.peters.html +.. [1] http://www.stackless.com +.. [2] http://web.archive.org/web/20000815070602/http://world.std.com/~wware/uthread.html +.. [3] Demo/threads/Generator.py in the source distribution +.. [4] http://www.stackless.com/coroutines.tim.peters.html - -Local Variables: -mode: indented-text -indent-tabs-mode: nil -End: + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + End: diff --git a/pep-0228.txt b/pep-0228.txt index 061c8a382..c32395970 100644 --- a/pep-0228.txt +++ b/pep-0228.txt @@ -5,140 +5,152 @@ Last-Modified: $Date$ Author: moshez@zadka.site.co.il (Moshe Zadka), guido@python.org (Guido van Rossum) Status: Withdrawn Type: Standards Track +Content-Type: text/x-rst Created: 4-Nov-2000 -Python-Version: ?? Post-History: Withdrawal +========== - This PEP has been withdrawn in favor of PEP 3141. +This PEP has been withdrawn in favor of PEP 3141. Abstract +======== - Today, Python's numerical model is similar to the C numeric model: - there are several unrelated numerical types, and when operations - between numerical types are requested, coercions happen. While - the C rationale for the numerical model is that it is very similar - to what happens at the hardware level, that rationale does not - apply to Python. So, while it is acceptable to C programmers that - 2/3 == 0, it is surprising to many Python programmers. +Today, Python's numerical model is similar to the C numeric model: +there are several unrelated numerical types, and when operations +between numerical types are requested, coercions happen. While +the C rationale for the numerical model is that it is very similar +to what happens at the hardware level, that rationale does not +apply to Python. So, while it is acceptable to C programmers that +2/3 == 0, it is surprising to many Python programmers. - NOTE: in the light of recent discussions in the newsgroup, the - motivation in this PEP (and details) need to be extended. +NOTE: in the light of recent discussions in the newsgroup, the +motivation in this PEP (and details) need to be extended. Rationale +========= - In usability studies, one of the least usable aspect of Python was - the fact that integer division returns the floor of the division. - This makes it hard to program correctly, requiring casts to - float() in various parts through the code. Python's numerical - model stems from C, while a model that might be easier to work with - can be based on the mathematical understanding of numbers. +In usability studies, one of the least usable aspect of Python was +the fact that integer division returns the floor of the division. +This makes it hard to program correctly, requiring casts to +``float()`` in various parts through the code. Python's numerical +model stems from C, while a model that might be easier to work with +can be based on the mathematical understanding of numbers. Other Numerical Models +====================== - Perl's numerical model is that there is one type of numbers -- - floating point numbers. While it is consistent and superficially - non-surprising, it tends to have subtle gotchas. One of these is - that printing numbers is very tricky, and requires correct - rounding. In Perl, there is also a mode where all numbers are - integers. This mode also has its share of problems, which arise - from the fact that there is not even an approximate way of - dividing numbers and getting meaningful answers. +Perl's numerical model is that there is one type of numbers -- +floating point numbers. While it is consistent and superficially +non-surprising, it tends to have subtle gotchas. One of these is +that printing numbers is very tricky, and requires correct +rounding. In Perl, there is also a mode where all numbers are +integers. This mode also has its share of problems, which arise +from the fact that there is not even an approximate way of +dividing numbers and getting meaningful answers. Suggested Interface For Python's Numerical Model +================================================ - While coercion rules will remain for add-on types and classes, the - built in type system will have exactly one Python type -- a - number. There are several things which can be considered "number - methods": +While coercion rules will remain for add-on types and classes, the +built in type system will have exactly one Python type -- a +number. There are several things which can be considered "number +methods": - 1. isnatural() - 2. isintegral() - 3. isrational() - 4. isreal() - 5. iscomplex() +1. ``isnatural()`` +2. ``isintegral()`` +3. ``isrational()`` +4. ``isreal()`` +5. ``iscomplex()`` +6. ``isexact()`` - a. isexact() +Obviously, a number which answers true to a question from 1 to 5, will +also answer true to any following question. If ``isexact()`` is not true, +then any answer might be wrong. +(But not horribly wrong: it's close to the truth.) - Obviously, a number which answers true to a question from 1 to 5, will - also answer true to any following question. If "isexact()" is not true, - then any answer might be wrong. - (But not horribly wrong: it's close to the truth.) +Now, there is two thing the models promises for the field operations +(+, -, /, \*): - Now, there is two thing the models promises for the field operations - (+, -, /, *): +- If both operands satisfy ``isexact()``, the result satisfies + ``isexact()``. - - If both operands satisfy isexact(), the result satisfies - isexact(). +- All field rules are true, except that for not-``isexact()`` numbers, + they might be only approximately true. - - All field rules are true, except that for not-isexact() numbers, - they might be only approximately true. +One consequence of these two rules is that all exact calcutions +are done as (complex) rationals: since the field laws must hold, +then:: - One consequence of these two rules is that all exact calcutions - are done as (complex) rationals: since the field laws must hold, - then + (a/b)*b == a - (a/b)*b == a +must hold. - must hold. +There is built-in function, ``inexact()`` which takes a number +and returns an inexact number which is a good approximation. +Inexact numbers must be as least as accurate as if they were +using IEEE-754. - There is built-in function, inexact() which takes a number - and returns an inexact number which is a good approximation. - Inexact numbers must be as least as accurate as if they were - using IEEE-754. +Several of the classical Python functions will return exact numbers +even when given inexact numbers: e.g, ``int()``. - Several of the classical Python functions will return exact numbers - even when given inexact numbers: e.g, int(). Coercion +======== + +The number type does not define ``nb_coerce`` +Any numeric operation slot, when receiving something other then ``PyNumber``, +refuses to implement it. - The number type does not define nb_coerce - Any numeric operation slot, when receiving something other then PyNumber, - refuses to implement it. Inexact Operations +================== - The functions in the "math" module will be allowed to return - inexact results for exact values. However, they will never return - a non-real number. The functions in the "cmath" module are also - allowed to return an inexact result for an exact argument, and are - furthermore allowed to return a complex result for a real - argument. +The functions in the ``math`` module will be allowed to return +inexact results for exact values. However, they will never return +a non-real number. The functions in the ``cmath`` module are also +allowed to return an inexact result for an exact argument, and are +furthermore allowed to return a complex result for a real +argument. Numerical Python Issues +======================= - People who use Numerical Python do so for high-performance vector - operations. Therefore, NumPy should keep its hardware based - numeric model. +People who use Numerical Python do so for high-performance vector +operations. Therefore, NumPy should keep its hardware based +numeric model. Unresolved Issues +================= - Which number literals will be exact, and which inexact? +Which number literals will be exact, and which inexact? - How do we deal with IEEE 754 operations? (probably, isnan/isinf should - be methods) +How do we deal with IEEE 754 operations? (probably, isnan/isinf should +be methods) - On 64-bit machines, comparisons between ints and floats may be - broken when the comparison involves conversion to float. Ditto - for comparisons between longs and floats. This can be dealt with - by avoiding the conversion to float. (Due to Andrew Koenig.) +On 64-bit machines, comparisons between ints and floats may be +broken when the comparison involves conversion to float. Ditto +for comparisons between longs and floats. This can be dealt with +by avoiding the conversion to float. (Due to Andrew Koenig.) Copyright +========= - This document has been placed in the public domain. +This document has been placed in the public domain. - -Local Variables: -mode: indented-text -indent-tabs-mode: nil -End: + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + End: diff --git a/pep-0235.txt b/pep-0235.txt index 933df9d5d..3445ecd25 100644 --- a/pep-0235.txt +++ b/pep-0235.txt @@ -5,27 +5,30 @@ Last-Modified: $Date$ Author: Tim Peters Status: Final Type: Standards Track +Content-Type: text/x-rst Created: Python-Version: 2.1 Post-History: 16 February 2001 Note +==== - This is essentially a retroactive PEP: the issue came up too late - in the 2.1 release process to solicit wide opinion before deciding - what to do, and can't be put off until 2.2 without also delaying - the Cygwin and MacOS X ports. +This is essentially a retroactive PEP: the issue came up too late +in the 2.1 release process to solicit wide opinion before deciding +what to do, and can't be put off until 2.2 without also delaying +the Cygwin and MacOS X ports. Motivation +========== - File systems vary across platforms in whether or not they preserve - the case of filenames, and in whether or not the platform C - library file-opening functions do or don't insist on - case-sensitive matches: +File systems vary across platforms in whether or not they preserve +the case of filenames, and in whether or not the platform C +library file-opening functions do or don't insist on +case-sensitive matches:: - case-preserving case-destroying + case-preserving case-destroying +-------------------+------------------+ case-sensitive | most Unix flavors | brrrrrrrrrr | +-------------------+------------------+ @@ -35,119 +38,122 @@ Motivation | | OpenVMS | +-------------------+------------------+ - In the upper left box, if you create "fiLe" it's stored as "fiLe", - and only open("fiLe") will open it (open("file") will not, nor - will the 14 other variations on that theme). +In the upper left box, if you create "fiLe" it's stored as "fiLe", +and only ``open("fiLe")`` will open it ``(open("file")`` will not, nor +will the 14 other variations on that theme). - In the lower right box, if you create "fiLe", there's no telling - what it's stored as -- but most likely as "FILE" -- and any of the - 16 obvious variations on open("FilE") will open it. +In the lower right box, if you create "fiLe", there's no telling +what it's stored as -- but most likely as "FILE" -- and any of the +16 obvious variations on ``open("FilE")`` will open it. - The lower left box is a mix: creating "fiLe" stores "fiLe" in the - platform directory, but you don't have to match case when opening - it; any of the 16 obvious variations on open("FILe") work. +The lower left box is a mix: creating "fiLe" stores "fiLe" in the +platform directory, but you don't have to match case when opening +it; any of the 16 obvious variations on ``open("FILe")`` work. - NONE OF THAT IS CHANGING! Python will continue to follow platform - conventions w.r.t. whether case is preserved when creating a file, - and w.r.t. whether open() requires a case-sensitive match. In - practice, you should always code as if matches were - case-sensitive, else your program won't be portable. +NONE OF THAT IS CHANGING! Python will continue to follow platform +conventions w.r.t. whether case is preserved when creating a file, +and w.r.t. whether ``open()`` requires a case-sensitive match. In +practice, you should always code as if matches were +case-sensitive, else your program won't be portable. - What's proposed is to change the semantics of Python "import" - statements, and there *only* in the lower left box. +What's proposed is to change the semantics of Python "import" +statements, and there *only* in the lower left box. Current Lower-Left Semantics +============================ - Support for MacOSX HFS+, and for Cygwin, is new in 2.1, so nothing - is changing there. What's changing is Windows behavior. Here are - the current rules for import on Windows: +Support for MacOSX HFS+, and for Cygwin, is new in 2.1, so nothing +is changing there. What's changing is Windows behavior. Here are +the current rules for import on Windows: - 1. Despite that the filesystem is case-insensitive, Python insists - on a case-sensitive match. But not in the way the upper left - box works: if you have two files, FiLe.py and file.py on - sys.path, and do +1. Despite that the filesystem is case-insensitive, Python insists + on a case-sensitive match. But not in the way the upper left + box works: if you have two files, ``FiLe.py`` and ``file.py`` on + ``sys.path``, and do:: - import file + import file - then if Python finds FiLe.py first, it raises a NameError. It - does *not* go on to find file.py; indeed, it's impossible to - import any but the first case-insensitive match on sys.path, - and then only if case matches exactly in the first - case-insensitive match. +then if Python finds ``FiLe.py`` first, it raises a ``NameError``. It +does *not* go on to find ``file.py``; indeed, it's impossible to +import any but the first case-insensitive match on ``sys.path``, +and then only if case matches exactly in the first +case-insensitive match. - 2. An ugly exception: if the first case-insensitive match on - sys.path is for a file whose name is entirely in upper case - (FILE.PY or FILE.PYC or FILE.PYO), then the import silently - grabs that, no matter what mixture of case was used in the - import statement. This is apparently to cater to miserable old - filesystems that really fit in the lower right box. But this - exception is unique to Windows, for reasons that may or may not - exist. +2. An ugly exception: if the first case-insensitive match on + ``sys.path`` is for a file whose name is entirely in upper case + (``FILE.PY`` or ``FILE.PYC`` or ``FILE.PYO``), then the import silently + grabs that, no matter what mixture of case was used in the + import statement. This is apparently to cater to miserable old + filesystems that really fit in the lower right box. But this + exception is unique to Windows, for reasons that may or may not + exist. - 3. And another exception: if the environment variable PYTHONCASEOK - exists, Python silently grabs the first case-insensitive match - of any kind. +3. And another exception: if the environment variable ``PYTHONCASEOK`` + exists, Python silently grabs the first case-insensitive match + of any kind. - So these Windows rules are pretty complicated, and neither match - the Unix rules nor provide semantics natural for the native - filesystem. That makes them hard to explain to Unix *or* Windows - users. Nevertheless, they've worked fine for years, and in - isolation there's no compelling reason to change them. +So these Windows rules are pretty complicated, and neither match +the Unix rules nor provide semantics natural for the native +filesystem. That makes them hard to explain to Unix *or* Windows +users. Nevertheless, they've worked fine for years, and in +isolation there's no compelling reason to change them. - However, that was before the MacOSX HFS+ and Cygwin ports arrived. - They also have case-preserving case-insensitive filesystems, but - the people doing the ports despised the Windows rules. Indeed, a - patch to make HFS+ act like Unix for imports got past a reviewer - and into the code base, which incidentally made Cygwin also act - like Unix (but this met the unbounded approval of the Cygwin - folks, so they sure didn't complain -- they had patches of their - own pending to do this, but the reviewer for those balked). +However, that was before the MacOSX HFS+ and Cygwin ports arrived. +They also have case-preserving case-insensitive filesystems, but +the people doing the ports despised the Windows rules. Indeed, a +patch to make HFS+ act like Unix for imports got past a reviewer +and into the code base, which incidentally made Cygwin also act +like Unix (but this met the unbounded approval of the Cygwin +folks, so they sure didn't complain -- they had patches of their +own pending to do this, but the reviewer for those balked). - At a higher level, we want to keep Python consistent, by following - the same rules on *all* platforms with case-preserving - case-insensitive filesystems. +At a higher level, we want to keep Python consistent, by following +the same rules on *all* platforms with case-preserving +case-insensitive filesystems. Proposed Semantics +================== - The proposed new semantics for the lower left box: +The proposed new semantics for the lower left box: - A. If the PYTHONCASEOK environment variable exists, same as - before: silently accept the first case-insensitive match of any - kind; raise ImportError if none found. +A. If the ``PYTHONCASEOK`` environment variable exists, same as + before: silently accept the first case-insensitive match of any + kind; raise ImportError if none found. - B. Else search sys.path for the first case-sensitive match; raise - ImportError if none found. +B. Else search ``sys.path`` for the first case-sensitive match; raise + ``ImportError`` if none found. - #B is the same rule as is used on Unix, so this will improve cross- - platform portability. That's good. #B is also the rule the Mac - and Cygwin folks want (and wanted enough to implement themselves, - multiple times, which is a powerful argument in PythonLand). It - can't cause any existing non-exceptional Windows import to fail, - because any existing non-exceptional Windows import finds a - case-sensitive match first in the path -- and it still will. An - exceptional Windows import currently blows up with a NameError or - ImportError, in which latter case it still will, or in which - former case will continue searching, and either succeed or blow up - with an ImportError. +#B is the same rule as is used on Unix, so this will improve cross- +platform portability. That's good. #B is also the rule the Mac +and Cygwin folks want (and wanted enough to implement themselves, +multiple times, which is a powerful argument in PythonLand). It +can't cause any existing non-exceptional Windows import to fail, +because any existing non-exceptional Windows import finds a +case-sensitive match first in the path -- and it still will. An +exceptional Windows import currently blows up with a ``NameError`` or +``ImportError``, in which latter case it still will, or in which +former case will continue searching, and either succeed or blow up +with an ``ImportError``. - #A is needed to cater to case-destroying filesystems mounted on Windows, - and *may* also be used by people so enamored of "natural" Windows - behavior that they're willing to set an environment variable to - get it. I don't intend to implement #A for Unix too, but that's - just because I'm not clear on how I *could* do so efficiently (I'm - not going to slow imports under Unix just for theoretical purity). +#A is needed to cater to case-destroying filesystems mounted on Windows, +and *may* also be used by people so enamored of "natural" Windows +behavior that they're willing to set an environment variable to +get it. I don't intend to implement #A for Unix too, but that's +just because I'm not clear on how I *could* do so efficiently (I'm +not going to slow imports under Unix just for theoretical purity). - The potential damage is here: #2 (matching on ALLCAPS.PY) is - proposed to be dropped. Case-destroying filesystems are a - vanishing breed, and support for them is ugly. We're already - supporting (and will continue to support) PYTHONCASEOK for their - benefit, but they don't deserve multiple hacks in 2001. +The potential damage is here: #2 (matching on ``ALLCAPS.PY``) is +proposed to be dropped. Case-destroying filesystems are a +vanishing breed, and support for them is ugly. We're already +supporting (and will continue to support) ``PYTHONCASEOK`` for their +benefit, but they don't deserve multiple hacks in 2001. - -Local Variables: -mode: indented-text -indent-tabs-mode: nil -End: + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + End: diff --git a/pep-0269.txt b/pep-0269.txt index 52f180b17..18d203772 100644 --- a/pep-0269.txt +++ b/pep-0269.txt @@ -5,184 +5,216 @@ Last-Modified: $Date$ Author: jriehl@spaceship.com (Jonathan Riehl) Status: Deferred Type: Standards Track +Content-Type: text/x-rst Created: 24-Aug-2001 Python-Version: 2.2 Post-History: Abstract +======== - Much like the parser module exposes the Python parser, this PEP - proposes that the parser generator used to create the Python - parser, pgen, be exposed as a module in Python. +Much like the parser module exposes the Python parser, this PEP +proposes that the parser generator used to create the Python +parser, ``pgen``, be exposed as a module in Python. Rationale +========= - Through the course of Pythonic history, there have been numerous - discussions about the creation of a Python compiler [1]. These - have resulted in several implementations of Python parsers, most - notably the parser module currently provided in the Python - standard library[2] and Jeremy Hylton's compiler module[3]. - However, while multiple language changes have been proposed - [4][5], experimentation with the Python syntax has lacked the - benefit of a Python binding to the actual parser generator used to - build Python. +Through the course of Pythonic history, there have been numerous +discussions about the creation of a Python compiler [1]_. These +have resulted in several implementations of Python parsers, most +notably the parser module currently provided in the Python +standard library [2]_ and Jeremy Hylton's compiler module [3]_. +However, while multiple language changes have been proposed +[4]_ [5]_, experimentation with the Python syntax has lacked the +benefit of a Python binding to the actual parser generator used to +build Python. - By providing a Python wrapper analogous to Fred Drake Jr.'s parser - wrapper, but targeted at the pgen library, the following - assertions are made: +By providing a Python wrapper analogous to Fred Drake Jr.'s parser +wrapper, but targeted at the ``pgen`` library, the following +assertions are made: - 1. Reference implementations of syntax changes will be easier to - develop. Currently, a reference implementation of a syntax - change would require the developer to use the pgen tool from - the command line. The resulting parser data structure would - then either have to be reworked to interface with a custom - CPython implementation, or wrapped as a C extension module. +1. Reference implementations of syntax changes will be easier to + develop. Currently, a reference implementation of a syntax + change would require the developer to use the ``pgen`` tool from + the command line. The resulting parser data structure would + then either have to be reworked to interface with a custom + CPython implementation, or wrapped as a C extension module. - 2. Reference implementations of syntax changes will be easier to - distribute. Since the parser generator will be available in - Python, it should follow that the resulting parser will - accessible from Python. Therefore, reference implementations - should be available as pure Python code, versus using custom - versions of the existing CPython distribution, or as compilable - extension modules. +2. Reference implementations of syntax changes will be easier to + distribute. Since the parser generator will be available in + Python, it should follow that the resulting parser will + accessible from Python. Therefore, reference implementations + should be available as pure Python code, versus using custom + versions of the existing CPython distribution, or as compilable + extension modules. - 3. Reference implementations of syntax changes will be easier to - discuss with a larger audience. This somewhat falls out of the - second assertion, since the community of Python users is most - likely larger than the community of CPython developers. +3. Reference implementations of syntax changes will be easier to + discuss with a larger audience. This somewhat falls out of the + second assertion, since the community of Python users is most + likely larger than the community of CPython developers. - 4. Development of small languages in Python will be further - enhanced, since the additional module will be a fully - functional LL(1) parser generator. +4. Development of small languages in Python will be further + enhanced, since the additional module will be a fully + functional LL(1) parser generator. Specification +============= - The proposed module will be called pgen. The pgen module will - contain the following functions: +The proposed module will be called ``pgen``. The ``pgen`` module will +contain the following functions: - parseGrammarFile (fileName) -> AST - The parseGrammarFile() function will read the file pointed to - by fileName and create an AST object. The AST nodes will - contain the nonterminal, numeric values of the parser - generator meta-grammar. The output AST will be an instance of - the AST extension class as provided by the parser module. - Syntax errors in the input file will cause the SyntaxError - exception to be raised. - parseGrammarString (text) -> AST - The parseGrammarString() function will follow the semantics of - the parseGrammarFile(), but accept the grammar text as a - string for input, as opposed to the file name. +``parseGrammarFile (fileName) -> AST`` +-------------------------------------- - buildParser (grammarAst) -> DFA - The buildParser() function will accept an AST object for input - and return a DFA (deterministic finite automaton) data - structure. The DFA data structure will be a C extension - class, much like the AST structure is provided in the parser - module. If the input AST does not conform to the nonterminal - codes defined for the pgen meta-grammar, buildParser() will - throw a ValueError exception. +The ``parseGrammarFile()`` function will read the file pointed to +by fileName and create an AST object. The AST nodes will +contain the nonterminal, numeric values of the parser +generator meta-grammar. The output AST will be an instance of +the AST extension class as provided by the parser module. +Syntax errors in the input file will cause the SyntaxError +exception to be raised. - parseFile (fileName, dfa, start) -> AST - The parseFile() function will essentially be a wrapper for the - PyParser_ParseFile() C API function. The wrapper code will - accept the DFA C extension class, and the file name. An AST - instance that conforms to the lexical values in the token - module and the nonterminal values contained in the DFA will be - output. - parseString (text, dfa, start) -> AST - The parseString() function will operate in a similar fashion - to the parseFile() function, but accept the parse text as an - argument. Much like parseFile() will wrap the - PyParser_ParseFile() C API function, parseString() will wrap - the PyParser_ParseString() function. +``parseGrammarString (text) -> AST`` +------------------------------------ - symbolToStringMap (dfa) -> dict - The symbolToStringMap() function will accept a DFA instance - and return a dictionary object that maps from the DFA's - numeric values for its nonterminals to the string names of the - nonterminals as found in the original grammar specification - for the DFA. +The ``parseGrammarString()`` function will follow the semantics of +the ``parseGrammarFile()``, but accept the grammar text as a +string for input, as opposed to the file name. - stringToSymbolMap (dfa) -> dict - The stringToSymbolMap() function output a dictionary mapping - the nonterminal names of the input DFA to their corresponding - numeric values. - Extra credit will be awarded if the map generation functions and - parsing functions are also methods of the DFA extension class. +``buildParser (grammarAst) -> DFA`` +----------------------------------- + +The ``buildParser()`` function will accept an AST object for input +and return a DFA (deterministic finite automaton) data +structure. The DFA data structure will be a C extension +class, much like the AST structure is provided in the parser +module. If the input AST does not conform to the nonterminal +codes defined for the ``pgen`` meta-grammar, ``buildParser()`` will +throw a ``ValueError`` exception. + + +``parseFile (fileName, dfa, start) -> AST`` +------------------------------------------- + +The ``parseFile()`` function will essentially be a wrapper for the +``PyParser_ParseFile()`` C API function. The wrapper code will +accept the DFA C extension class, and the file name. An AST +instance that conforms to the lexical values in the token +module and the nonterminal values contained in the DFA will be +output. + + +``parseString (text, dfa, start) -> AST`` +----------------------------------------- + +The ``parseString()`` function will operate in a similar fashion +to the ``parseFile()`` function, but accept the parse text as an +argument. Much like ``parseFile()`` will wrap the +``PyParser_ParseFile()`` C API function, ``parseString()`` will wrap +the ``PyParser_ParseString()`` function. + + +``symbolToStringMap (dfa) -> dict`` +----------------------------------- + +The ``symbolToStringMap()`` function will accept a DFA instance +and return a dictionary object that maps from the DFA's +numeric values for its nonterminals to the string names of the +nonterminals as found in the original grammar specification +for the DFA. + + +``stringToSymbolMap (dfa) -> dict`` +----------------------------------- + +The ``stringToSymbolMap()`` function output a dictionary mapping +the nonterminal names of the input DFA to their corresponding +numeric values. + + +Extra credit will be awarded if the map generation functions and +parsing functions are also methods of the DFA extension class. Implementation Plan +=================== - A cunning plan has been devised to accomplish this enhancement: +A cunning plan has been devised to accomplish this enhancement: - 1. Rename the pgen functions to conform to the CPython naming - standards. This action may involve adding some header files to - the Include subdirectory. +1. Rename the ``pgen`` functions to conform to the CPython naming + standards. This action may involve adding some header files to + the Include subdirectory. - 2. Move the pgen C modules in the Makefile.pre.in from unique pgen - elements to the Python C library. +2. Move the ``pgen`` C modules in the Makefile.pre.in from unique ``pgen`` + elements to the Python C library. - 3. Make any needed changes to the parser module so the AST - extension class understands that there are AST types it may not - understand. Cursory examination of the AST extension class - shows that it keeps track of whether the tree is a suite or an - expression. +3. Make any needed changes to the parser module so the AST + extension class understands that there are AST types it may not + understand. Cursory examination of the AST extension class + shows that it keeps track of whether the tree is a suite or an + expression. - 3. Code an additional C module in the Modules directory. The C - extension module will implement the DFA extension class and the - functions outlined in the previous section. +3. Code an additional C module in the Modules directory. The C + extension module will implement the DFA extension class and the + functions outlined in the previous section. - 4. Add the new module to the build process. Black magic, indeed. +4. Add the new module to the build process. Black magic, indeed. Limitations +=========== - Under this proposal, would be designers of Python 3000 will still - be constrained to Python's lexical conventions. The addition, - subtraction or modification of the Python lexer is outside the - scope of this PEP. +Under this proposal, would be designers of Python 3000 will still +be constrained to Python's lexical conventions. The addition, +subtraction or modification of the Python lexer is outside the +scope of this PEP. Reference Implementation +======================== - No reference implementation is currently provided. A patch - was provided at some point in - http://sourceforge.net/tracker/index.php?func=detail&aid=599331&group_id=5470&atid=305470 - but that patch is no longer maintained. +No reference implementation is currently provided. A patch +was provided at some point in +http://sourceforge.net/tracker/index.php?func=detail&aid=599331&group_id=5470&atid=305470 +but that patch is no longer maintained. References +========== - [1] The (defunct) Python Compiler-SIG - http://www.python.org/sigs/compiler-sig/ +.. [1] The (defunct) Python Compiler-SIG + http://www.python.org/sigs/compiler-sig/ - [2] Parser Module Documentation - http://docs.python.org/library/parser.html +.. [2] Parser Module Documentation + http://docs.python.org/library/parser.html - [3] Hylton, Jeremy. - http://docs.python.org/library/compiler.html +.. [3] Hylton, Jeremy. + http://docs.python.org/library/compiler.html - [4] Pelletier, Michel. "Python Interface Syntax", PEP-245. - http://www.python.org/dev/peps/pep-0245/ +.. [4] Pelletier, Michel. "Python Interface Syntax", PEP-245. + http://www.python.org/dev/peps/pep-0245/ - [5] The Python Types-SIG - http://www.python.org/sigs/types-sig/ +.. [5] The Python Types-SIG + http://www.python.org/sigs/types-sig/ Copyright +========= - This document has been placed in the public domain. +This document has been placed in the public domain. - -Local Variables: -mode: indented-text -indent-tabs-mode: nil -fill-column: 70 -End: + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + fill-column: 70 + End: diff --git a/pep-0288.txt b/pep-0288.txt index 3a594161d..88bcfa0a9 100644 --- a/pep-0288.txt +++ b/pep-0288.txt @@ -5,159 +5,168 @@ Last-Modified: $Date$ Author: python@rcn.com (Raymond Hettinger) Status: Withdrawn Type: Standards Track +Content-Type: text/x-rst Created: 21-Mar-2002 Python-Version: 2.5 Post-History: Abstract +======== - This PEP proposes to enhance generators by providing mechanisms for - raising exceptions and sharing data with running generators. +This PEP proposes to enhance generators by providing mechanisms for +raising exceptions and sharing data with running generators. Status +====== - This PEP is withdrawn. The exception raising mechanism was extended - and subsumed into PEP 343. The attribute passing capability - never built a following, did not have a clear implementation, - and did not have a clean way for the running generator to access - its own namespace. +This PEP is withdrawn. The exception raising mechanism was extended +and subsumed into PEP 343. The attribute passing capability +never built a following, did not have a clear implementation, +and did not have a clean way for the running generator to access +its own namespace. Rationale +========= - Currently, only class based iterators can provide attributes and - exception handling. However, class based iterators are harder to - write, less compact, less readable, and slower. A better solution - is to enable these capabilities for generators. +Currently, only class based iterators can provide attributes and +exception handling. However, class based iterators are harder to +write, less compact, less readable, and slower. A better solution +is to enable these capabilities for generators. - Enabling attribute assignments allows data to be passed to and from - running generators. The approach of sharing data using attributes - pervades Python. Other approaches exist but are somewhat hackish - in comparison. +Enabling attribute assignments allows data to be passed to and from +running generators. The approach of sharing data using attributes +pervades Python. Other approaches exist but are somewhat hackish +in comparison. - Another evolutionary step is to add a generator method to allow - exceptions to be passed to a generator. Currently, there is no - clean method for triggering exceptions from outside the generator. - Also, generator exception passing helps mitigate the try/finally - prohibition for generators. The need is especially acute for - generators needing to flush buffers or close resources upon termination. - - The two proposals are backwards compatible and require no new - keywords. They are being recommended for Python version 2.5. +Another evolutionary step is to add a generator method to allow +exceptions to be passed to a generator. Currently, there is no +clean method for triggering exceptions from outside the generator. +Also, generator exception passing helps mitigate the try/finally +prohibition for generators. The need is especially acute for +generators needing to flush buffers or close resources upon termination. + +The two proposals are backwards compatible and require no new +keywords. They are being recommended for Python version 2.5. Specification for Generator Attributes +====================================== - Essentially, the proposal is to emulate attribute writing for classes. - The only wrinkle is that generators lack a way to refer to instances of - themselves. So, the proposal is to provide a function for discovering - the reference. For example: +Essentially, the proposal is to emulate attribute writing for classes. +The only wrinkle is that generators lack a way to refer to instances of +themselves. So, the proposal is to provide a function for discovering +the reference. For example:: - def mygen(filename): - self = sys.get_generator() - myfile = open(filename) - for line in myfile: - if len(line) < 10: - continue - self.pos = myfile.tell() - yield line.upper() + def mygen(filename): + self = sys.get_generator() + myfile = open(filename) + for line in myfile: + if len(line) < 10: + continue + self.pos = myfile.tell() + yield line.upper() - g = mygen('sample.txt') - line1 = g.next() - print 'Position', g.pos + g = mygen('sample.txt') + line1 = g.next() + print 'Position', g.pos - Uses for generator attributes include: +Uses for generator attributes include: - 1. Providing generator clients with extra information (as shown - above). - 2. Externally setting control flags governing generator operation - (possibly telling a generator when to step in or step over - data groups). - 3. Writing lazy consumers with complex execution states - (an arithmetic encoder output stream for example). - 4. Writing co-routines (as demonstrated in Dr. Mertz's articles [1]). +1. Providing generator clients with extra information (as shown + above). +2. Externally setting control flags governing generator operation + (possibly telling a generator when to step in or step over + data groups). +3. Writing lazy consumers with complex execution states + (an arithmetic encoder output stream for example). +4. Writing co-routines (as demonstrated in Dr. Mertz's articles [1]_). - The control flow of 'yield' and 'next' is unchanged by this - proposal. The only change is that data can passed to and from the - generator. Most of the underlying machinery is already in place, - only the access function needs to be added. +The control flow of 'yield' and 'next' is unchanged by this +proposal. The only change is that data can passed to and from the +generator. Most of the underlying machinery is already in place, +only the access function needs to be added. -Specification for Generator Exception Passing: +Specification for Generator Exception Passing +============================================= - Add a .throw(exception) method to the generator interface: +Add a .throw(exception) method to the generator interface:: - def logger(): - start = time.time() - log = [] - try: - while True: - log.append(time.time() - start) - yield log[-1] - except WriteLog: - writelog(log) + def logger(): + start = time.time() + log = [] + try: + while True: + log.append(time.time() - start) + yield log[-1] + except WriteLog: + writelog(log) - g = logger() - for i in [10,20,40,80,160]: - testsuite(i) - g.next() - g.throw(WriteLog) + g = logger() + for i in [10,20,40,80,160]: + testsuite(i) + g.next() + g.throw(WriteLog) - There is no existing work-around for triggering an exception - inside a generator. It is the only case in Python where active - code cannot be excepted to or through. +There is no existing work-around for triggering an exception +inside a generator. It is the only case in Python where active +code cannot be excepted to or through. - Generator exception passing also helps address an intrinsic - limitation on generators, the prohibition against their using - try/finally to trigger clean-up code [2]. +Generator exception passing also helps address an intrinsic +limitation on generators, the prohibition against their using +try/finally to trigger clean-up code [2]_. - Note A: The name of the throw method was selected for several - reasons. Raise is a keyword and so cannot be used as a method - name. Unlike raise which immediately raises an exception from the - current execution point, throw will first return to the generator - and then raise the exception. The word throw is suggestive of - putting the exception in another location. The word throw is - already associated with exceptions in other languages. +Note A: The name of the throw method was selected for several +reasons. Raise is a keyword and so cannot be used as a method +name. Unlike raise which immediately raises an exception from the +current execution point, throw will first return to the generator +and then raise the exception. The word throw is suggestive of +putting the exception in another location. The word throw is +already associated with exceptions in other languages. - Alternative method names were considered: resolve(), signal(), - genraise(), raiseinto(), and flush(). None of these fit as well - as throw(). +Alternative method names were considered: ``resolve()``, ``signal()``, +``genraise()``, ``raiseinto()``, and ``flush()``. None of these fit as well +as ``throw()``. - Note B: To keep the throw() syntax simple only the instance - version of the raise syntax would be supported (no variants for - "raise string" or "raise class, instance"). +Note B: To keep the ``throw()`` syntax simple only the instance +version of the raise syntax would be supported (no variants for +"raise string" or "raise class, instance"). - Calling "g.throw(instance)" would correspond to writing - "raise instance" immediately after the most recent yield. +Calling ``g.throw(instance)`` would correspond to writing +``raise instance`` immediately after the most recent yield. References +========== - [1] Dr. David Mertz's draft columns for Charming Python: - http://gnosis.cx/publish/programming/charming_python_b5.txt - http://gnosis.cx/publish/programming/charming_python_b7.txt +.. [1] Dr. David Mertz's draft columns for Charming Python + http://gnosis.cx/publish/programming/charming_python_b5.txt + http://gnosis.cx/publish/programming/charming_python_b7.txt - [2] PEP 255 Simple Generators: - http://www.python.org/dev/peps/pep-0255/ +.. [2] PEP 255 Simple Generators + http://www.python.org/dev/peps/pep-0255/ - [3] Proof-of-concept recipe: - http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/164044 +.. [3] Proof-of-concept recipe + http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/164044 Copyright +========= - This document has been placed in the public domain. +This document has been placed in the public domain. -Local Variables: -mode: indented-text -indent-tabs-mode: nil -fill-column: 70 -End: +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + fill-column: 70 + End: diff --git a/pep-0312.txt b/pep-0312.txt index 82a93b550..b1db8148c 100644 --- a/pep-0312.txt +++ b/pep-0312.txt @@ -5,181 +5,205 @@ Last-Modified: $Date$ Author: Roman Suzi , Alex Martelli Status: Deferred Type: Standards Track -Content-Type: text/plain +Content-Type: text/x-rst Created: 11-Feb-2003 Python-Version: 2.4 Post-History: Abstract +======== + +This PEP proposes to make argumentless lambda keyword optional in +some cases where it is not grammatically ambiguous. - This PEP proposes to make argumentless lambda keyword optional in - some cases where it is not grammatically ambiguous. Deferral +======== - The BDFL hates the unary colon syntax. This PEP needs to go back - to the drawing board and find a more Pythonic syntax (perhaps an - alternative unary operator). See python-dev discussion on - 17 June 2005. +The BDFL hates the unary colon syntax. This PEP needs to go back +to the drawing board and find a more Pythonic syntax (perhaps an +alternative unary operator). See python-dev discussion on +17 June 2005 [1]_. + +Also, it is probably a good idea to eliminate the alternative +propositions which have no chance at all. The examples section +is good and highlights the readability improvements. It would +carry more weight with additional examples and with real-world +referents (instead of the abstracted dummy calls to ``:A`` and ``:B``). - Also, it is probably a good idea to eliminate the alternative - propositions which have no chance at all. The examples section - is good and highlights the readability improvements. It would - carry more weight with additional examples and with real-world - referents (instead of the abstracted dummy calls to :A and :B). Motivation +========== - Lambdas are useful for defining anonymous functions, e.g. for use - as callbacks or (pseudo)-lazy evaluation schemes. Often, lambdas - are not used when they would be appropriate, just because the - keyword "lambda" makes code look complex. Omitting lambda in some - special cases is possible, with small and backwards compatible - changes to the grammar, and provides a cheap cure against such - "lambdaphobia". +Lambdas are useful for defining anonymous functions, e.g. for use +as callbacks or (pseudo)-lazy evaluation schemes. Often, lambdas +are not used when they would be appropriate, just because the +keyword "lambda" makes code look complex. Omitting lambda in some +special cases is possible, with small and backwards compatible +changes to the grammar, and provides a cheap cure against such +"lambdaphobia". Rationale +========= - Sometimes people do not use lambdas because they fear to introduce - a term with a theory behind it. This proposal makes introducing - argumentless lambdas easier, by omitting the "lambda" keyword. - itself. Implementation can be done simply changing grammar so it - lets the "lambda" keyword be implied in a few well-known cases. - In particular, adding surrounding brackets lets you specify - nullary lambda anywhere. +Sometimes people do not use lambdas because they fear to introduce +a term with a theory behind it. This proposal makes introducing +argumentless lambdas easier, by omitting the "lambda" keyword. +itself. Implementation can be done simply changing grammar so it +lets the "lambda" keyword be implied in a few well-known cases. +In particular, adding surrounding brackets lets you specify +nullary lambda anywhere. Syntax +====== - An argumentless "lambda" keyword can be omitted in the following - cases: +An argumentless "lambda" keyword can be omitted in the following +cases: - * immediately after "=" in named parameter assignment or default - value assignment; +* immediately after "=" in named parameter assignment or default + value assignment; - * immediately after "(" in any expression; +* immediately after "(" in any expression; - * immediately after a "," in a function argument list; +* immediately after a "," in a function argument list; - * immediately after a ":" in a dictionary literal; (not - implemented) +* immediately after a ":" in a dictionary literal; (not + implemented) - * in an assignment statement; (not implemented) +* in an assignment statement; (not implemented) Examples of Use +=============== - 1) Inline "if": +1) Inline ``if``:: - def ifelse(cond, true_part, false_part): - if cond: - return true_part() - else: - return false_part() + def ifelse(cond, true_part, false_part): + if cond: + return true_part() + else: + return false_part() - # old syntax: - print ifelse(a < b, lambda:A, lambda:B) + # old syntax: + print ifelse(a < b, lambda:A, lambda:B) - # new syntax: - print ifelse(a < b, :A, :B) + # new syntax: + print ifelse(a < b, :A, :B) - # parts A and B may require extensive processing, as in: - print ifelse(a < b, :ext_proc1(A), :ext_proc2(B)) + # parts A and B may require extensive processing, as in: + print ifelse(a < b, :ext_proc1(A), :ext_proc2(B)) - 2) Locking: +2) Locking:: - def with(alock, acallable): - alock.acquire() - try: - acallable() - finally: - alock.release() + def with(alock, acallable): + alock.acquire() + try: + acallable() + finally: + alock.release() - with(mylock, :x(y(), 23, z(), 'foo')) + with(mylock, :x(y(), 23, z(), 'foo')) Implementation +============== - Implementation requires some tweaking of the Grammar/Grammar file - in the Python sources, and some adjustment of - Modules/parsermodule.c to make syntactic and pragmatic changes. +Implementation requires some tweaking of the Grammar/Grammar file +in the Python sources, and some adjustment of +Modules/parsermodule.c to make syntactic and pragmatic changes. - (Some grammar/parser guru is needed to make a full - implementation.) +(Some grammar/parser guru is needed to make a full +implementation.) - Here are the changes needed to Grammar to allow implicit lambda: +Here are the changes needed to Grammar to allow implicit lambda:: - varargslist: (fpdef ['=' imptest] ',')* ('*' NAME [',' '**' - NAME] | '**' NAME) | fpdef ['=' imptest] (',' fpdef ['=' - imptest])* [','] + varargslist: (fpdef ['=' imptest] ',')* ('*' NAME [',' '**' + NAME] | '**' NAME) | fpdef ['=' imptest] (',' fpdef ['=' + imptest])* [','] - imptest: test | implambdef + imptest: test | implambdef - atom: '(' [imptestlist] ')' | '[' [listmaker] ']' | - '{' [dictmaker] '}' | '`' testlist1 '`' | NAME | NUMBER | STRING+ + atom: '(' [imptestlist] ')' | '[' [listmaker] ']' | + '{' [dictmaker] '}' | '`' testlist1 '`' | NAME | NUMBER | STRING+ - implambdef: ':' test + implambdef: ':' test - imptestlist: imptest (',' imptest)* [','] + imptestlist: imptest (',' imptest)* [','] - argument: [test '='] imptest + argument: [test '='] imptest - Three new non-terminals are needed: imptest for the place where - implicit lambda may occur, implambdef for the implicit lambda - definition itself, imptestlist for a place where imptest's may - occur. +Three new non-terminals are needed: ``imptest`` for the place where +implicit lambda may occur, ``implambdef`` for the implicit lambda +definition itself, ``imptestlist`` for a place where ``imptest``'s may +occur. - This implementation is not complete. First, because some files in - Parser module need to be updated. Second, some additional places - aren't implemented, see Syntax section above. +This implementation is not complete. First, because some files in +Parser module need to be updated. Second, some additional places +aren't implemented, see Syntax section above. Discussion +========== - This feature is not a high-visibility one (the only novel part is - the absence of lambda). The feature is intended to make null-ary - lambdas more appealing syntactically, to provide lazy evaluation - of expressions in some simple cases. This proposal is not targeted - at more advanced cases (demanding arguments for the lambda). +This feature is not a high-visibility one (the only novel part is +the absence of lambda). The feature is intended to make null-ary +lambdas more appealing syntactically, to provide lazy evaluation +of expressions in some simple cases. This proposal is not targeted +at more advanced cases (demanding arguments for the lambda). - There is an alternative proposition for implicit lambda: implicit - lambda with unused arguments. In this case the function defined by - such lambda can accept any parameters, i.e. be equivalent to: - lambda *args: expr. This form would be more powerful. Grep in the - standard library revealed that such lambdas are indeed in use. +There is an alternative proposition for implicit lambda: implicit +lambda with unused arguments. In this case the function defined by +such lambda can accept any parameters, i.e. be equivalent to: +``lambda *args: expr``. This form would be more powerful. Grep in the +standard library revealed that such lambdas are indeed in use. - One more extension can provide a way to have a list of parameters - passed to a function defined by implicit lambda. However, such - parameters need some special name to be accessed and are unlikely - to be included in the language. Possible local names for such - parameters are: _, __args__, __. For example: +One more extension can provide a way to have a list of parameters +passed to a function defined by implicit lambda. However, such +parameters need some special name to be accessed and are unlikely +to be included in the language. Possible local names for such +parameters are: ``_``, ``__args__``, ``__``. For example:: - reduce(:_[0] + _[1], [1,2,3], 0) - reduce(:__[0] + __[1], [1,2,3], 0) - reduce(:__args__[0] + __args__[1], [1,2,3], 0) + reduce(:_[0] + _[1], [1,2,3], 0) + reduce(:__[0] + __[1], [1,2,3], 0) + reduce(:__args__[0] + __args__[1], [1,2,3], 0) - These forms do not look very nice, and in the PEP author's opinion - do not justify the removal of the lambda keyword in such cases. +These forms do not look very nice, and in the PEP author's opinion +do not justify the removal of the lambda keyword in such cases. Credits +======= + +The idea of dropping lambda was first coined by Paul Rubin at 08 +Feb 2003 16:39:30 -0800 in comp.lang.python while discussing the +thread "For review: PEP 308 - If-then-else expression" [2]_. + + +References +========== + +.. [1] Guido van Rossum, Recommend accepting PEP 312 -- Simple Implicit Lambda + https://mail.python.org/pipermail/python-dev/2005-June/054304.html + +.. [2] Guido van Rossum, For review: PEP 308 - If-then-else expression + https://mail.python.org/pipermail/python-dev/2003-February/033178.html - The idea of dropping lambda was first coined by Paul Rubin at 08 - Feb 2003 16:39:30 -0800 in comp.lang.python while discussing the - thread "For review: PEP 308 - If-then-else expression". Copyright +========= - This document has been placed in the public domain. +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 -End: + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 70 + End: diff --git a/pep-0315.txt b/pep-0315.txt index cc638621c..ee1dabf3f 100644 --- a/pep-0315.txt +++ b/pep-0315.txt @@ -2,160 +2,176 @@ PEP: 315 Title: Enhanced While Loop Version: $Revision$ Last-Modified: $Date$ -Author: Raymond Hettinger - W Isaac Carroll +Author: Raymond Hettinger , W Isaac Carroll Status: Rejected Type: Standards Track -Content-Type: text/plain +Content-Type: text/x-rst Created: 25-Apr-2003 Python-Version: 2.5 Post-History: Abstract +======== - This PEP proposes adding an optional "do" clause to the beginning - of the while loop to make loop code clearer and reduce errors - caused by code duplication. +This PEP proposes adding an optional "do" clause to the beginning +of the while loop to make loop code clearer and reduce errors +caused by code duplication. Notice +====== - Rejected; see - http://mail.python.org/pipermail/python-ideas/2013-June/021610.html +Rejected; see [1]_. - This PEP has been deferred since 2006; see - http://mail.python.org/pipermail/python-dev/2006-February/060718.html +This PEP has been deferred since 2006; see [2]_. - Subsequent efforts to revive the PEP in April 2009 did not - meet with success because no syntax emerged that could - compete with the following form: +Subsequent efforts to revive the PEP in April 2009 did not +meet with success because no syntax emerged that could +compete with the following form:: - while True: - - if not : - break - + while True: + + if not : + break + - A syntax alternative to the one proposed in the PEP was found for - a basic do-while loop but it gained little support because the - condition was at the top: +A syntax alternative to the one proposed in the PEP was found for +a basic do-while loop but it gained little support because the +condition was at the top:: - do ... while : - + do ... while : + - Users of the language are advised to use the while-True form with - an inner if-break when a do-while loop would have been appropriate. +Users of the language are advised to use the while-True form with +an inner if-break when a do-while loop would have been appropriate. Motivation +========== - It is often necessary for some code to be executed before each - evaluation of the while loop condition. This code is often - duplicated outside the loop, as setup code that executes once - before entering the loop: +It is often necessary for some code to be executed before each +evaluation of the while loop condition. This code is often +duplicated outside the loop, as setup code that executes once +before entering the loop:: + + while : + - while : - - - The problem is that duplicated code can be a source of errors if - one instance is changed but the other is not. Also, the purpose - of the second instance of the setup code is not clear because it - comes at the end of the loop. +The problem is that duplicated code can be a source of errors if +one instance is changed but the other is not. Also, the purpose +of the second instance of the setup code is not clear because it +comes at the end of the loop. - It is possible to prevent code duplication by moving the loop - condition into a helper function, or an if statement in the loop - body. However, separating the loop condition from the while - keyword makes the behavior of the loop less clear: +It is possible to prevent code duplication by moving the loop +condition into a helper function, or an if statement in the loop +body. However, separating the loop condition from the while +keyword makes the behavior of the loop less clear:: - def helper(args): - - return + def helper(args): + + return - while helper(args): - + while helper(args): + - This last form has the additional drawback of requiring the loop's - else clause to be added to the body of the if statement, further - obscuring the loop's behavior: +This last form has the additional drawback of requiring the loop's +else clause to be added to the body of the if statement, further +obscuring the loop's behavior:: - while True: - - if not : break - + while True: + + if not : break + - This PEP proposes to solve these problems by adding an optional - clause to the while loop, which allows the setup code to be - expressed in a natural way: +This PEP proposes to solve these problems by adding an optional +clause to the while loop, which allows the setup code to be +expressed in a natural way:: - do: - - while : - + do: + + while : + - This keeps the loop condition with the while keyword where it - belongs, and does not require code to be duplicated. +This keeps the loop condition with the while keyword where it +belongs, and does not require code to be duplicated. Syntax +====== - The syntax of the while statement +The syntax of the while statement:: - while_stmt : "while" expression ":" suite - ["else" ":" suite] + while_stmt : "while" expression ":" suite + ["else" ":" suite] - is extended as follows: +is extended as follows:: - while_stmt : ["do" ":" suite] - "while" expression ":" suite - ["else" ":" suite] + while_stmt : ["do" ":" suite] + "while" expression ":" suite + ["else" ":" suite] Semantics of break and continue +=============================== - In the do-while loop the break statement will behave the same as - in the standard while loop: It will immediately terminate the loop - without evaluating the loop condition or executing the else - clause. +In the do-while loop the break statement will behave the same as +in the standard while loop: It will immediately terminate the loop +without evaluating the loop condition or executing the else +clause. - A continue statement in the do-while loop jumps to the while - condition check. +A continue statement in the do-while loop jumps to the while +condition check. - In general, when the while suite is empty (a pass statement), - the do-while loop and break and continue statements should match - the semantics of do-while in other languages. +In general, when the while suite is empty (a pass statement), +the do-while loop and break and continue statements should match +the semantics of do-while in other languages. - Likewise, when the do suite is empty, the do-while loop and - break and continue statements should match behavior found - in regular while loops. +Likewise, when the do suite is empty, the do-while loop and +break and continue statements should match behavior found +in regular while loops. Future Statement +================ - Because of the new keyword "do", the statement +Because of the new keyword "do", the statement:: - from __future__ import do_while + from __future__ import do_while - will initially be required to use the do-while form. +will initially be required to use the do-while form. Implementation +============== - The first implementation of this PEP can compile the do-while loop - as an infinite loop with a test that exits the loop. +The first implementation of this PEP can compile the do-while loop +as an infinite loop with a test that exits the loop. + + +References +========== + +.. [1] Guido van Rossum, PEP 315: do-while + https://mail.python.org/pipermail/python-ideas/2013-June/021610.html + +.. [2] Raymond Hettinger, release plan for 2.5 ? + https://mail.python.org/pipermail/python-dev/2006-February/060718.html Copyright +========= - This document is placed in the public domain. +This document is placed in the public domain. - -Local Variables: -mode: indented-text -indent-tabs-mode: nil -sentence-end-double-space: t -fill-column: 75 -End: + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 75 + End: diff --git a/pep-3102.txt b/pep-3102.txt index 867423dbc..b76dd08f9 100644 --- a/pep-3102.txt +++ b/pep-3102.txt @@ -5,186 +5,193 @@ Last-Modified: $Date$ Author: Talin Status: Final Type: Standards Track -Content-Type: text/plain +Content-Type: text/x-rst Created: 22-Apr-2006 Python-Version: 3.0 Post-History: 28-Apr-2006, May-19-2006 Abstract +======== - This PEP proposes a change to the way that function arguments are - assigned to named parameter slots. In particular, it enables the - declaration of "keyword-only" arguments: arguments that can only - be supplied by keyword and which will never be automatically - filled in by a positional argument. +This PEP proposes a change to the way that function arguments are +assigned to named parameter slots. In particular, it enables the +declaration of "keyword-only" arguments: arguments that can only +be supplied by keyword and which will never be automatically +filled in by a positional argument. Rationale +========= - The current Python function-calling paradigm allows arguments to - be specified either by position or by keyword. An argument can be - filled in either explicitly by name, or implicitly by position. +The current Python function-calling paradigm allows arguments to +be specified either by position or by keyword. An argument can be +filled in either explicitly by name, or implicitly by position. - There are often cases where it is desirable for a function to take - a variable number of arguments. The Python language supports this - using the 'varargs' syntax ('*name'), which specifies that any - 'left over' arguments be passed into the varargs parameter as a - tuple. +There are often cases where it is desirable for a function to take +a variable number of arguments. The Python language supports this +using the 'varargs' syntax (``*name``), which specifies that any +'left over' arguments be passed into the varargs parameter as a +tuple. - One limitation on this is that currently, all of the regular - argument slots must be filled before the vararg slot can be. +One limitation on this is that currently, all of the regular +argument slots must be filled before the vararg slot can be. - This is not always desirable. One can easily envision a function - which takes a variable number of arguments, but also takes one - or more 'options' in the form of keyword arguments. Currently, - the only way to do this is to define both a varargs argument, - and a 'keywords' argument (**kwargs), and then manually extract - the desired keywords from the dictionary. +This is not always desirable. One can easily envision a function +which takes a variable number of arguments, but also takes one +or more 'options' in the form of keyword arguments. Currently, +the only way to do this is to define both a varargs argument, +and a 'keywords' argument (``**kwargs``), and then manually extract +the desired keywords from the dictionary. Specification +============= - Syntactically, the proposed changes are fairly simple. The first - change is to allow regular arguments to appear after a varargs - argument: +Syntactically, the proposed changes are fairly simple. The first +change is to allow regular arguments to appear after a varargs +argument:: - def sortwords(*wordlist, case_sensitive=False): - ... + def sortwords(*wordlist, case_sensitive=False): + ... - This function accepts any number of positional arguments, and it - also accepts a keyword option called 'case_sensitive'. This - option will never be filled in by a positional argument, but - must be explicitly specified by name. +This function accepts any number of positional arguments, and it +also accepts a keyword option called 'case_sensitive'. This +option will never be filled in by a positional argument, but +must be explicitly specified by name. - Keyword-only arguments are not required to have a default value. - Since Python requires that all arguments be bound to a value, - and since the only way to bind a value to a keyword-only argument - is via keyword, such arguments are therefore 'required keyword' - arguments. Such arguments must be supplied by the caller, and - they must be supplied via keyword. +Keyword-only arguments are not required to have a default value. +Since Python requires that all arguments be bound to a value, +and since the only way to bind a value to a keyword-only argument +is via keyword, such arguments are therefore 'required keyword' +arguments. Such arguments must be supplied by the caller, and +they must be supplied via keyword. - The second syntactical change is to allow the argument name to - be omitted for a varargs argument. The meaning of this is to - allow for keyword-only arguments for functions that would not - otherwise take a varargs argument: +The second syntactical change is to allow the argument name to +be omitted for a varargs argument. The meaning of this is to +allow for keyword-only arguments for functions that would not +otherwise take a varargs argument:: - def compare(a, b, *, key=None): - ... + def compare(a, b, *, key=None): + ... - The reasoning behind this change is as follows. Imagine for a - moment a function which takes several positional arguments, as - well as a keyword argument: +The reasoning behind this change is as follows. Imagine for a +moment a function which takes several positional arguments, as +well as a keyword argument:: - def compare(a, b, key=None): - ... + def compare(a, b, key=None): + ... - Now, suppose you wanted to have 'key' be a keyword-only argument. - Under the above syntax, you could accomplish this by adding a - varargs argument immediately before the keyword argument: +Now, suppose you wanted to have 'key' be a keyword-only argument. +Under the above syntax, you could accomplish this by adding a +varargs argument immediately before the keyword argument:: - def compare(a, b, *ignore, key=None): - ... + def compare(a, b, *ignore, key=None): + ... - Unfortunately, the 'ignore' argument will also suck up any - erroneous positional arguments that may have been supplied by the - caller. Given that we'd prefer any unwanted arguments to raise an - error, we could do this: +Unfortunately, the 'ignore' argument will also suck up any +erroneous positional arguments that may have been supplied by the +caller. Given that we'd prefer any unwanted arguments to raise an +error, we could do this:: - def compare(a, b, *ignore, key=None): - if ignore: # If ignore is not empty - raise TypeError + def compare(a, b, *ignore, key=None): + if ignore: # If ignore is not empty + raise TypeError + +As a convenient shortcut, we can simply omit the 'ignore' name, +meaning 'don't allow any positional arguments beyond this point'. + +(Note: After much discussion of alternative syntax proposals, the +BDFL has pronounced in favor of this 'single star' syntax for +indicating the end of positional parameters.) - As a convenient shortcut, we can simply omit the 'ignore' name, - meaning 'don't allow any positional arguments beyond this point'. - - (Note: After much discussion of alternative syntax proposals, the - BDFL has pronounced in favor of this 'single star' syntax for - indicating the end of positional parameters.) - Function Calling Behavior +========================= - The previous section describes the difference between the old - behavior and the new. However, it is also useful to have a - description of the new behavior that stands by itself, without - reference to the previous model. So this next section will - attempt to provide such a description. +The previous section describes the difference between the old +behavior and the new. However, it is also useful to have a +description of the new behavior that stands by itself, without +reference to the previous model. So this next section will +attempt to provide such a description. - When a function is called, the input arguments are assigned to - formal parameters as follows: +When a function is called, the input arguments are assigned to +formal parameters as follows: - - For each formal parameter, there is a slot which will be used - to contain the value of the argument assigned to that - parameter. +- For each formal parameter, there is a slot which will be used + to contain the value of the argument assigned to that + parameter. - - Slots which have had values assigned to them are marked as - 'filled'. Slots which have no value assigned to them yet are - considered 'empty'. +- Slots which have had values assigned to them are marked as + 'filled'. Slots which have no value assigned to them yet are + considered 'empty'. - - Initially, all slots are marked as empty. +- Initially, all slots are marked as empty. - - Positional arguments are assigned first, followed by keyword - arguments. +- Positional arguments are assigned first, followed by keyword + arguments. - - For each positional argument: +- For each positional argument: - o Attempt to bind the argument to the first unfilled - parameter slot. If the slot is not a vararg slot, then - mark the slot as 'filled'. + * Attempt to bind the argument to the first unfilled + parameter slot. If the slot is not a vararg slot, then + mark the slot as 'filled'. - o If the next unfilled slot is a vararg slot, and it does - not have a name, then it is an error. + * If the next unfilled slot is a vararg slot, and it does + not have a name, then it is an error. - o Otherwise, if the next unfilled slot is a vararg slot then - all remaining non-keyword arguments are placed into the - vararg slot. + * Otherwise, if the next unfilled slot is a vararg slot then + all remaining non-keyword arguments are placed into the + vararg slot. - - For each keyword argument: +- For each keyword argument: - o If there is a parameter with the same name as the keyword, - then the argument value is assigned to that parameter slot. - However, if the parameter slot is already filled, then that - is an error. + * If there is a parameter with the same name as the keyword, + then the argument value is assigned to that parameter slot. + However, if the parameter slot is already filled, then that + is an error. - o Otherwise, if there is a 'keyword dictionary' argument, - the argument is added to the dictionary using the keyword - name as the dictionary key, unless there is already an - entry with that key, in which case it is an error. + * Otherwise, if there is a 'keyword dictionary' argument, + the argument is added to the dictionary using the keyword + name as the dictionary key, unless there is already an + entry with that key, in which case it is an error. - o Otherwise, if there is no keyword dictionary, and no - matching named parameter, then it is an error. + * Otherwise, if there is no keyword dictionary, and no + matching named parameter, then it is an error. - - Finally: +- Finally: - o If the vararg slot is not yet filled, assign an empty tuple - as its value. + * If the vararg slot is not yet filled, assign an empty tuple + as its value. - o For each remaining empty slot: if there is a default value - for that slot, then fill the slot with the default value. - If there is no default value, then it is an error. + * For each remaining empty slot: if there is a default value + for that slot, then fill the slot with the default value. + If there is no default value, then it is an error. - In accordance with the current Python implementation, any errors - encountered will be signaled by raising TypeError. (If you want - something different, that's a subject for a different PEP.) +In accordance with the current Python implementation, any errors +encountered will be signaled by raising ``TypeError``. (If you want +something different, that's a subject for a different PEP.) Backwards Compatibility +======================= - The function calling behavior specified in this PEP is a superset - of the existing behavior - that is, it is expected that any - existing programs will continue to work. +The function calling behavior specified in this PEP is a superset +of the existing behavior - that is, it is expected that any +existing programs will continue to work. Copyright +========= - This document has been placed in the public domain. +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: + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 70 + coding: utf-8 + End: