<br><br><div><span class="gmail_quote">On 4/30/07, <b class="gmail_sendername">Phillip J. Eby</b> <<a href="mailto:pje@telecommunity.com">pje@telecommunity.com</a>> wrote:</span><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
This is just the first draft (also checked into SVN), and doesn't include<br>the details of how the extension API works (so that third-party interfaces<br>and generic functions can interoperate using the same decorators,
<br>annotations, etc.).<br><br>Comments and questions appreciated, as it'll help drive better explanations<br>of both the design and rationales. I'm usually not that good at guessing<br>what other people will want to know (or are likely to misunderstand) until
<br>I get actual questions.<br><br><br>PEP: 3124<br>Title: Overloading, Generic Functions, Interfaces, and Adaptation<br>Version: $Revision: 55029 $<br>Last-Modified: $Date: 2007-04-30 18:48:06 -0400 (Mon, 30 Apr 2007) $<br>
Author: Phillip J. Eby <<a href="mailto:pje@telecommunity.com">pje@telecommunity.com</a>><br>Discussions-To: Python 3000 List <<a href="mailto:python-3000@python.org">python-3000@python.org</a>><br>Status: Draft
<br>Type: Standards Track<br>Requires: 3107, 3115, 3119<br>Replaces: 245, 246<br>Content-Type: text/x-rst<br>Created: 28-Apr-2007<br>Post-History: 30-Apr-2007</blockquote><div><br><br>[SNIP]<br> </div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br>The ``@overload`` decorator allows you to define alternate<br>implementations of a function, specialized by argument type(s). A<br>function with the same name must already exist in the local namespace.<br>The existing function is modified in-place by the decorator to add
<br>the new implementation, and the modified function is returned by the<br>decorator. Thus, the following code::<br><br> from overloading import overload<br> from collections import Iterable<br><br> def flatten(ob):
<br> """Flatten an object to its component iterables"""<br> yield ob<br><br> @overload<br> def flatten(ob: Iterable):<br> for o in ob:<br> for ob in flatten(o):
<br> yield ob<br><br> @overload<br> def flatten(ob: basestring):<br> yield ob</blockquote><div><br><br>Doubt there is a ton of use for it, but any way to use this for pattern matching ala Standard ML or Haskell? Would be kind of neat to be able to do recursive function definitions and choose which specific function implementation based on the length of an argument. But I don't see how that would be possible with this directly. I guess if a SingularSequence type was defined that overloaded __isinstance__ properly maybe? I have not followed the __isinstance__ discussion closely so I am not sure.
<br> </div>[SNIP]<br><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><br>Proceeding to the "Next" Method<br>~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<br><br>If the first parameter of an overloaded function is named<br>``__proceed__``, it will be passed a callable representing the next<br>most-specific method. For example, this code::<br><br> def foo(bar:object, baz:object):
<br> print "got objects!"<br><br> @overload<br> def foo(__proceed__, bar:int, baz:int):<br> print "got integers!"<br> return __proceed__(bar, baz)<br><br>Will print "got integers!" followed by "got objects!".
<br><br>If there is no next most-specific method, ``__proceed__`` will be<br>bound to a ``NoApplicableMethods`` instance. When called, a new<br>``NoApplicableMethods`` instance will be raised, with the arguments<br>passed to the first instance.
<br><br>Similarly, if the next most-specific methods have ambiguous precedence<br>with respect to each other, ``__proceed__`` will be bound to an<br>``AmbiguousMethods`` instance, and if called, it will raise a new<br>instance.
<br><br>Thus, a method can either check if ``__proceed__`` is an error<br>instance, or simply invoke it. The ``NoApplicableMethods`` and<br>``AmbiguousMethods`` error classes have a common ``DispatchError``<br>base class, so ``isinstance(__proceed__,
overloading.DispatchError)``<br>is sufficient to identify whether ``__proceed__`` can be safely<br>called.<br><br>(Implementation note: using a magic argument name like ``__proceed__``<br>could potentially be replaced by a magic function that would be called
<br>to obtain the next method. A magic function, however, would degrade<br>performance and might be more difficult to implement on non-CPython<br>platforms. Method chaining via magic argument names, however, can be<br>efficiently implemented on any Python platform that supports creating
<br>bound methods from functions -- one simply recursively binds each<br>function to be chained, using the following function or error as the<br>``im_self`` of the bound method.)</blockquote><div><br><br>Could you change __proceed__ to be a keyword-only argument? That way it would match the precedence of class definitions and the 'metaclass' keyword introduced by PEP 3115. I personally would prefer to control what the default is if __proceed__ is not passed in at the parameter level then have to do a check if it's NoApplicableMethod.
<br> </div>-Brett</div>