Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread Antoine Pitrou
On Thu, 23 May 2013 02:33:57 -0400
Devin Jeanpierre  wrote:
> On Thu, May 23, 2013 at 2:04 AM, Antoine Pitrou  wrote:
> > On Thu, 23 May 2013 12:12:26 +1000
> > Nick Coghlan  wrote:
> >> The binary operators can be more accurately said to use a complicated
> >> single-dispatch dance rather than supporting native dual-dispatch.
> >
> > Not one based on the type of a single argument, though.
> 
> Why not?
> 
> I'd expect it to look something like this:
> 
> @singledispatch
> def ladd(left, right):
> return NotImplemented
> 
> @singledispatch
> def radd(right, left):
> return NotImplemented
> 
> def add(left, right):
> x = ladd(left, right)
> if x is not NotImplemented:
> return x
> x = radd(right, left)
> if x is not NotImplemented:
> return x
> raise TypeError
> 
> Then instead of defining __add__ you define an overloaded
> implementation of ladd, and instead of defining __radd__ you define an
> overloaded implementation of radd.

Well, I don't think you can say add() dispatches based on the type of a
single argument. But that may be a question of how you like to think
about decomposed problems.

Regards

Antoine.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread Armin Rigo
Hi,

On Thu, May 23, 2013 at 12:33 AM, Łukasz Langa  wrote:
> Alternative approaches
> ==

You could also mention "pairtype", used in PyPy:
https://bitbucket.org/pypy/pypy/raw/default/rpython/tool/pairtype.py
(very short code).  It's originally about adding double-dispatch, but
the usage that grew out of it is for generic single-dispatch functions
that are bound to some common "state" object as follows (Python 2
syntax):

class MyRepr(object):
 ...state of my repr...

class __extend__(pairtype(MyRepr, int)):
def show((myrepr, x), y):
 print "hi, I'm the integer %d, arg is %s" % (x, y)

class __extend__(pairtype(MyRepr, list)):
def show((myrepr, x), y):
 print "hi, I'm a list"
 ...use myrepr to control the state...

pair(MyRepr(), [2,3,4]).show(42)


- Armin
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread Nick Coghlan
On 23 May 2013 16:37, "Devin Jeanpierre"  wrote:
>
> On Thu, May 23, 2013 at 2:04 AM, Antoine Pitrou 
wrote:
> > On Thu, 23 May 2013 12:12:26 +1000
> > Nick Coghlan  wrote:
> >> The binary operators can be more accurately said to use a complicated
> >> single-dispatch dance rather than supporting native dual-dispatch.
> >
> > Not one based on the type of a single argument, though.
>
> Why not?
>
> I'd expect it to look something like this:
>
> @singledispatch
> def ladd(left, right):
> return NotImplemented
>
> @singledispatch
> def radd(right, left):
> return NotImplemented
>
> def add(left, right):
> x = ladd(left, right)
> if x is not NotImplemented:
> return x
> x = radd(right, left)
> if x is not NotImplemented:
> return x
> raise TypeError
>
> Then instead of defining __add__ you define an overloaded
> implementation of ladd, and instead of defining __radd__ you define an
> overloaded implementation of radd.

That's the basic idea, but there's the extra complication that if
type(right) is a strict subclass of type(left), you try radd first.

Cheers,
Nick.

>
> -- Devin
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> http://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
http://mail.python.org/mailman/options/python-dev/ncoghlan%40gmail.com
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread Glenn Linderman

On 5/23/2013 12:14 AM, Antoine Pitrou wrote:

On Thu, 23 May 2013 02:33:57 -0400
Devin Jeanpierre  wrote:

>On Thu, May 23, 2013 at 2:04 AM, Antoine Pitrou  wrote:

> >On Thu, 23 May 2013 12:12:26 +1000
> >Nick Coghlan  wrote:

> >>The binary operators can be more accurately said to use a complicated
> >>single-dispatch dance rather than supporting native dual-dispatch.

> >
> >Not one based on the type of a single argument, though.

>
>Why not?
>
>I'd expect it to look something like this:
>
> @singledispatch
> def ladd(left, right):
> return NotImplemented
>
> @singledispatch
> def radd(right, left):
> return NotImplemented
>
> def add(left, right):
> x = ladd(left, right)
> if x is not NotImplemented:
> return x
> x = radd(right, left)
> if x is not NotImplemented:
> return x
> raise TypeError
>
>Then instead of defining __add__ you define an overloaded
>implementation of ladd, and instead of defining __radd__ you define an
>overloaded implementation of radd.

Well, I don't think you can say add() dispatches based on the type of a
single argument. But that may be a question of how you like to think
about decomposed problems.


I suspect the point was not that add can be described as doing single 
dispatch (it can't), but rather that add could possibly be implemented 
in terms of lower-level functions doing single dispatch. If that was the 
point, perhaps the next level point is trying to be that single dispatch 
is a sufficient mechanism that can be augmented (as above) to handle 
more complex cases. Whether the above (which I think would need to use 
raise and try instead of return and if) is sufficient to handle such 
cases is not yet proven. The case Guido mention where radd is tried 
before add would seem to require a bit more complex logic than the above.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread Antoine Pitrou
Le Thu, 23 May 2013 00:31:38 -0700,
Glenn Linderman  a écrit :
> 
> I suspect the point was not that add can be described as doing single 
> dispatch (it can't), but rather that add could possibly be
> implemented in terms of lower-level functions doing single dispatch.
> If that was the point, perhaps the next level point is trying to be
> that single dispatch is a sufficient mechanism that can be augmented
> (as above) to handle more complex cases.

This is true, but as it is of everything Turing-complete. Generic
functions don't add anything that you can't already do manually (for
example with custom registries) :-)

Regardless, I also agree that single-dispatch is much easier to reason
about, and good enough for now.

Regards

Antoine.


___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 442 delegate

2013-05-23 Thread Kristján Valur Jónsson

> Didn't know about Stackless Python. Is it faster than CPython?
> 
> I'm developing an application that takes more than 5000 active threads,
> sometimes up to 10.
> Will it benefit from Stackless Python?
> 
> Can I use it for WSGI with Apache httpd?
> 
Stackless has its own website and mailing list.
Please visit www.stackless.com for full info, since it is offtopic for this 
list.

K
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread Łukasz Langa
On 23 maj 2013, at 01:16, Terry Jan Reedy  wrote:

> I like the general idea. Does you have any specific stdlib use cases in mind?
> 
> I thought of pprint, which at some point dispatches on dict versus 
> set/sequence, but overall it seems more complicated than mere arg type 
> dispatch.

I want to make pprint extensible for 3.4 and PEP 443 started out as an idea to 
introduce a uniform API for the boilerplate I'm going to need anyway. It turned 
out the idea has been around for years.

> Unittest.TestCase.assertEqual mostly (but not completely) uses first arg 
> dispatch based on an instance-specific dict, and it has an custom instance 
> registration method addTypeEqualityFunc. (Since each test_xxx runs in a new 
> instance, a registration for multiple methods has to be done either in a 
> setup method or repeated in each test_method.)

If a registration mechanism is already in place, it will probably need to stay 
(backwards compatibility). The feasability of refactoring to @singledispatch 
will have to be considered on a case-by-case basis.

On a more general note, I'm sure that @singledispatch won't cover every use 
case. Still, PJE implemented both pkgutil.simplegeneric and PEAK-Rules because 
the former is the proverbial 20% that gets you 80% there. For those use cases 
the simplicity and transparency provided by a basic solution are a virtue. This 
is what PEP 443 targets.

If @singledispatch turns out so successful that we'll find ourselves longing 
for multiple dispatch or predicate-based dispatch in the future, I'm sure 
there's still going to be enough PEP numbers free. The @singledispatch name has 
been chosen to ensure there's no name clash in that case (thanks Nick for 
suggesting that!).

-- 
Best regards,
Łukasz Langa

WWW: http://lukasz.langa.pl/
Twitter: @llanga
IRC: ambv on #python-dev

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 409 and the stdlib

2013-05-23 Thread Martin v. Löwis
Am 21.05.13 18:03, schrieb Ethan Furman:
> And, of course, we only make these changes when we're already modifying
> the module for some other reason.

In the specific case, the KeyError has indeed useful information that
the TypeError does not, namely the specific character that is the culprit.

So if you do drop the KeyError entirely, please carry over information
about the character into the TypeError.

Regards,
Martin

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread Łukasz Langa
On 23 maj 2013, at 09:33, Armin Rigo  wrote:

> Hi,
> 
> On Thu, May 23, 2013 at 12:33 AM, Łukasz Langa  wrote:
>> Alternative approaches
>> ==
> 
> You could also mention "pairtype", used in PyPy:

Thanks for pointing that out. Information on it added
in http://hg.python.org/peps/rev/b7979219f3cc#l1.7

+PyPy's RPython offers ``extendabletype`` [#pairtype]_, a metaclass which
+enables classes to be externally extended. In combination with
+``pairtype()`` and ``pair()`` factories, this offers a form of
+single-dispatch generics.

+.. [#pairtype]
+   https://bitbucket.org/pypy/pypy/raw/default/rpython/tool/pairtype.py


-- 
Best regards,
Łukasz Langa

WWW: http://lukasz.langa.pl/
Twitter: @llanga
IRC: ambv on #python-dev

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 409 and the stdlib

2013-05-23 Thread Ethan Furman

On 05/23/2013 04:36 AM, "Martin v. Löwis" wrote:

Am 21.05.13 18:03, schrieb Ethan Furman:

And, of course, we only make these changes when we're already modifying
the module for some other reason.


In the specific case, the KeyError has indeed useful information that
the TypeError does not, namely the specific character that is the culprit.

So if you do drop the KeyError entirely, please carry over information
about the character into the TypeError.


Here's the code that existed at one point:

for c in s:
val = _b32rev.get(c)
if val is None:
raise TypeError('Non-base32 digit found')

Even though there is no KeyError to convert in this incarnation, providing the cause of failure is still appreciated by 
the user who's trying to figure out what, exactly, went wrong.


--
~Ethan~
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread Guido van Rossum
Łukasz, are there any open issues? Otherwise I'm ready to accept the PEP.

-- 
--Guido van Rossum (python.org/~guido)
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread Łukasz Langa
On 23 maj 2013, at 16:49, Guido van Rossum  wrote:

> Łukasz, are there any open issues? Otherwise I'm ready to accept the PEP.

There's one. Quoting the PEP:

"The dispatch type is currently specified as a decorator argument. The
implementation could allow a form using argument annotations. This usage
pattern is out of scope for the standard library (per PEP 8). However,
whether this registration form would be acceptable for general usage, is
up to debate."

I feel that the PEP should explicitly allow or disallow for the
implementation to accept dispatch on annotations, e.g.:

@func.register
def _(arg: int):
  ...

versus

@func.register(int)
def _(arg):
  ...

-- 
Best regards,
Łukasz Langa

WWW: http://lukasz.langa.pl/
Twitter: @llanga
IRC: ambv on #python-dev

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread Paul Moore
On 23 May 2013 15:58, Łukasz Langa  wrote:

> On 23 maj 2013, at 16:49, Guido van Rossum  wrote:
>
> > Łukasz, are there any open issues? Otherwise I'm ready to accept the PEP.
>
> There's one. Quoting the PEP:
>
> "The dispatch type is currently specified as a decorator argument. The
> implementation could allow a form using argument annotations. This usage
> pattern is out of scope for the standard library (per PEP 8). However,
> whether this registration form would be acceptable for general usage, is
> up to debate."
>
> I feel that the PEP should explicitly allow or disallow for the
> implementation to accept dispatch on annotations, e.g.:
>
> @func.register
> def _(arg: int):
>   ...
>
> versus
>
> @func.register(int)
> def _(arg):
>   ...


Personally, I think the register(int) form seems more natural. But that may
well be because there are no uses of annotations in the wild (at least not
in code I'm familiar with) and having this as an example of how annotations
can be used would help with adoption.

I'm not 100% sure what the options are.

1. Only support the register(int) form
2. Only support the annotation form
3. Support both annotation and argument forms

Is the debate between 1 and 2, or 1 and 3? Is it even possible to implement
3 without having 2 different names for "register"?

If the debate is between 1 and 2, I'd prefer 1. But if it's between 1 and
3, I'm less sure - having the *option* to try annotations for this in my
own code sounds useful.

Paul.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread Guido van Rossum
Ok, happy bikeshedding. I'm outta here until that's settled. :-)

On Thu, May 23, 2013 at 7:58 AM, Łukasz Langa  wrote:
> On 23 maj 2013, at 16:49, Guido van Rossum  wrote:
>
>> Łukasz, are there any open issues? Otherwise I'm ready to accept the PEP.
>
> There's one. Quoting the PEP:
>
> "The dispatch type is currently specified as a decorator argument. The
> implementation could allow a form using argument annotations. This usage
> pattern is out of scope for the standard library (per PEP 8). However,
> whether this registration form would be acceptable for general usage, is
> up to debate."
>
> I feel that the PEP should explicitly allow or disallow for the
> implementation to accept dispatch on annotations, e.g.:
>
> @func.register
> def _(arg: int):
>   ...
>
> versus
>
> @func.register(int)
> def _(arg):
>   ...
>
> --
> Best regards,
> Łukasz Langa
>
> WWW: http://lukasz.langa.pl/
> Twitter: @llanga
> IRC: ambv on #python-dev
>



-- 
--Guido van Rossum (python.org/~guido)
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread Ethan Furman

On 05/23/2013 07:58 AM, Łukasz Langa wrote:

On 23 maj 2013, at 16:49, Guido van Rossum  wrote:


Łukasz, are there any open issues? Otherwise I'm ready to accept the PEP.


There's one. Quoting the PEP:

"The dispatch type is currently specified as a decorator argument. The
implementation could allow a form using argument annotations. This usage
pattern is out of scope for the standard library (per PEP 8). However,
whether this registration form would be acceptable for general usage, is
up to debate."

I feel that the PEP should explicitly allow or disallow for the
implementation to accept dispatch on annotations, e.g.:

@func.register
def _(arg: int):
   ...

versus

@func.register(int)
def _(arg):
   ...


If the stdlib is still staying out of the annotation business, then it should 
not be allowed.

--
~Ethan~
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread Walter Dörwald

On 23.05.13 00:33, Łukasz Langa wrote:


Hello,
I would like to submit the following PEP for discussion and evaluation.


PEP: 443
Title: Single-dispatch generic functions
[...]
   >>> @fun.register(int)
   ... def _(arg, verbose=False):
   ... if verbose:
   ... print("Strength in numbers, eh?", end=" ")
   ... print(arg)
   ...


Should it be possible to register multiple types for the generic 
function with one register() call, i.e. should:


   @fun.register(int, float)
   def _(arg, verbose=False):
  ...

be allowed as a synonym for

   @fun.register(int)
   @fun.register(float)
   def _(arg, verbose=False):
  ...

Servus,
   Walter

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread Paul Moore
On 23 May 2013 17:00, Walter Dörwald  wrote:

> Should it be possible to register multiple types for the generic function
> with one register() call, i.e. should:
>
>@fun.register(int, float)
>def _(arg, verbose=False):
>   ...
>
> be allowed as a synonym for
>
>@fun.register(int)
>@fun.register(float)
>def _(arg, verbose=False):
>

No, because people will misread register(int, float) as meaning first
argument int, second float. The double decorator is explicit as to what is
going on, and isn't too hard to read or write.

Paul
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread Éric Araujo
Hi,

Thanks for writing this PEP.  Blessing one implementation for the stdlib
and one official backport will make programmers’ lives a bit easier :)

>   >>> @fun.register(int)
>   ... def _(arg, verbose=False):
>   ... if verbose:
>   ... print("Strength in numbers, eh?", end=" ")
>   ... print(arg)
>   ...

Does this work if the implementation function is called like the first
decorated function? (I don’t know the proper terminology) e.g.

>>> @fun.register(int)
... def fun(arg, verbose=False):
... if verbose:
... print("Strength in numbers, eh?", end=" ")
... print(arg)

The precedent is 2.6+ properties, where prop.setter mutates and returns
the property object, which then overwrites the previous name in the
class dictionary.

> * the current implementation relies on ``__mro__`` alone, making it
>   incompatible with Abstract Base Classes'
>   ``register()``/``unregister()`` functionality. A possible solution has
>   been proposed by PJE on the original issue for exposing
>   ``pkgutil.simplegeneric`` as part of the ``functools`` API
>   [#issue-5135]_.

Making generic functions work with ABCs sounds like a requirement to me,
as ABCs are baked into the language (isinstance).  ABCs and interfaces
(i.e. zope.interface) are really neat and powerful.

> * the dispatch type is currently specified as a decorator argument. The
>   implementation could allow a form using argument annotations. This
>   usage pattern is out of scope for the standard library [#pep-0008]_.
>   However, whether this registration form would be acceptable for
>   general usage, is up to debate.

+1 to passing the type as argument to the decorator and not supporting
annotations.  It’s simple and works.


Question: what happens if two functions (say in two different modules)
are registered for the same type?
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread Ethan Furman

User API


To define a generic function, decorate it with the ``@singledispatch``
decorator. Note that the dispatch happens on the type of the first
argument, create your function accordingly:

.. code-block:: pycon

   >>> from functools import singledispatch
   >>> @singledispatch
   ... def fun(arg, verbose=False):
   ... if verbose:
   ... print("Let me just say,", end=" ")
   ... print(arg)

To add overloaded implementations to the function, use the
``register()`` attribute of the generic function. It takes a type
parameter:

.. code-block:: pycon

   >>> @fun.register(int)
   ... def _(arg, verbose=False):
   ... if verbose:
   ... print("Strength in numbers, eh?", end=" ")
   ... print(arg)
   ...
   >>> @fun.register(list)
   ... def _(arg, verbose=False):
   ... if verbose:
   ... print("Enumerate this:")
   ... for i, elem in enumerate(arg):
   ... print(i, elem)

To enable registering lambdas and pre-existing functions, the
``register()`` attribute can be used in a functional form:

.. code-block:: pycon

   >>> def nothing(arg, verbose=False):
   ... print("Nothing.")
   ...
   >>> fun.register(type(None), nothing)



So to have a generic `mapping` function that worked on dicts, namedtuples, user-defined record types, etc., would look 
something like:


--> from functools import singledispatch

--> @singledispatch
--> def mapping(d):
... new_d = {}
... new_d.update(d)
... return new_d
...

--> @mapping.register(tuple)
... def _(t):
... names = getattr(t, '_fields', ['f%d' % n for n in range(len(t))])
... values = list(t)
... return dict(zip(names, values))
...

--> @mapping.register(user_class):
... def _(uc):
... blah blah
... return dict(more blah)
...

Very cool.  I'm looking forward to it!

Oh, the tuple example above is intended primarily for named tuples, but since there is no common base class besides 
tuple I had to also handle the case where a plain tuple is passed in, and personally I'd rather have generic field names 
than raise an exception.


--
~Ethan~
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread PJ Eby
On Thu, May 23, 2013 at 11:11 AM, Paul Moore  wrote:
> Is the debate between 1 and 2, or 1 and 3? Is it even possible to implement
> 3 without having 2 different names for "register"?

Yes.  You could do it as either:
@func.register
def doit(foo: int):
...

by checking for the first argument to register() being a function, or:

   @func.register()
def doit(foo: int):
...

by using a default None first argument.  In either case, you would
then raise a TypeError if there wasn't an annotation.

As to the ability to do multiple types registration, you could support
it only in type annotations, e.g.:

@func.register
def doit(foo: [int, float]):
...

without it being confused with being multiple dispatch.

One other thing about the register API that's currently unspecified in
the PEP: what does it return, exactly?

I generally lean towards returning the undecorated function, so that if you say:

@func.register
def do_int(foo: int):
...

You still have the option of calling it explicitly.  OTOH, some may
prefer to treat it like an overload and call it 'func' every time, in
which case register should return the generic function.  Some guidance
as to what should be the official One Obvious Way would be helpful
here.

(Personally, I usually name my methods explicitly because in debugging
it's a fast clue as to which piece of code I should be looking at.)
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread Ethan Furman

On 05/23/2013 11:13 AM, Éric Araujo wrote:


Thanks for writing this PEP.  Blessing one implementation for the stdlib
and one official backport will make programmers’ lives a bit easier :)


   >>> @fun.register(int)
   ... def _(arg, verbose=False):
   ... if verbose:
   ... print("Strength in numbers, eh?", end=" ")
   ... print(arg)
   ...


Does this work if the implementation function is called like the first
decorated function? (I don’t know the proper terminology) e.g.

 >>> @fun.register(int)
 ... def fun(arg, verbose=False):
 ... if verbose:
 ... print("Strength in numbers, eh?", end=" ")
 ... print(arg)

The precedent is 2.6+ properties, where prop.setter mutates and returns
the property object, which then overwrites the previous name in the
class dictionary.


Actually, properties return new instances:

--> class Test(object):
... _temp = 'fleeting'
... @property
... def temp(self):
... return self._temp
... @temp.setter
... def new_temp(self, value):
... self._temp = value
...

--> id(Test.temp)
30245384

--> id(Test.new_temp)
30246352

--> Test.temp is Test.new_temp
False

--
~Ethan~
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread PJ Eby
On Thu, May 23, 2013 at 2:59 PM, PJ Eby  wrote:
> I generally lean towards returning the undecorated function, so that if you 
> say:
>
> @func.register
> def do_int(foo: int):
> ...

Oops, forgot to mention:  one other advantage to returning the
undecorated function is that you can do this:

@func.register(int)
@func.register(float)
def do_num(foo):
   ...

Which neatly solves the multiple registration problem, even without
argument annotations.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread Łukasz Langa
On 23 maj 2013, at 20:59, PJ Eby  wrote:

> As to the ability to do multiple types registration, you could support
> it only in type annotations, e.g.:
> 
>@func.register
>def doit(foo: [int, float]):
>...

Initially I thought so, too. But it seems other people might think this
means "a sequence with the first element being an integer, and the second
a float". The BDFL seems to have yet a different idea:

http://mail.python.org/pipermail/python-ideas/2012-December/018129.html

This is clearly material for a separate PEP, wink wink, nudge nudge.

To the point though. Based on this, and the fact PEP 8 currently disallows
annotations within the standard library, I came to the conclusion that
currently we should not include the annotation-driven form.

> I generally lean towards returning the undecorated function, so that if you 
> say:
> 
>@func.register
>def do_int(foo: int):
>...

Me too. The PEP has been updated to specify that explicitly.

-- 
Best regards,
Łukasz Langa

WWW: http://lukasz.langa.pl/
Twitter: @llanga
IRC: ambv on #python-dev

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread Łukasz Langa
On 23 maj 2013, at 20:13, Éric Araujo  wrote:

> Does this work if the implementation function is called like the first
> decorated function?

No, the ``register()`` attribute returns the undecorated function which
enables decorator stacking, as well as creating unit tests for each
variant independently.

> Making generic functions work with ABCs sounds like a requirement to me

Yes, I will implement that.

> Question: what happens if two functions (say in two different modules)
> are registered for the same type?

Last one wins. Just like with assigning names in a scope, defining methods
in a class or overriding them in a subclass.

-- 
Best regards,
Łukasz Langa

WWW: http://lukasz.langa.pl/
Twitter: @llanga
IRC: ambv on #python-dev

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread Ethan Furman

On 05/23/2013 01:10 PM, Łukasz Langa wrote:

On 23 maj 2013, at 20:59, PJ Eby  wrote:


As to the ability to do multiple types registration, you could support
it only in type annotations, e.g.:

@func.register
def doit(foo: [int, float]):
...


Initially I thought so, too. But it seems other people might think this
means "a sequence with the first element being an integer, and the second
a float". The BDFL seems to have yet a different idea:

http://mail.python.org/pipermail/python-ideas/2012-December/018129.html

This is clearly material for a separate PEP, wink wink, nudge nudge.

To the point though. Based on this, and the fact PEP 8 currently disallows
annotations within the standard library, I came to the conclusion that
currently we should not include the annotation-driven form.


I generally lean towards returning the undecorated function, so that if you say:

@func.register
def do_int(foo: int):
...


Me too. The PEP has been updated to specify that explicitly.


So with this decision made, are there any open issues left?  Or can we invite 
Guido back to the discussion?  ;)

--
~Ethan~
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread Ronan Lamy
2013/5/23 Łukasz Langa 

> On 23 maj 2013, at 20:13, Éric Araujo  wrote:
>
> > Question: what happens if two functions (say in two different modules)
> > are registered for the same type?
>
> Last one wins. Just like with assigning names in a scope, defining methods
> in a class or overriding them in a subclass.
>

This is a serious annoyance, considering that there are several places
where a large library can reasonably define the implementations (i.e. with
the class, with the function, or in some utility module). Note that in
contrast with the case of functions in a module or methods in a class,
linting tools cannot be expected to detect a duplication between functions
with different names defined in different modules.

Another thing missing from the PEP is the ability to access the
implementation function when you know the generic function and the class. A
major use case for this is to define the implementation for a subclass by
reusing its parent's implementation, e.g. :

@some_generic.register(my_int)
def _(arg):
print("Hello from my_int!")
return some_generic[int](arg)

--
Ronan Lamy
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread Éric Araujo
Le 23/05/2013 16:10, Łukasz Langa a écrit :
>> Does this work if the implementation function is called like the first
>> decorated function?
> No, the ``register()`` attribute returns the undecorated function which
> enables decorator stacking, as well as creating unit tests for each
> variant independently.

Perfect.  My web framework of choice uses decorators that register
things and return the function as is and I love it.  I guess the common
pattern will be to use variants of the generic function name, e.g. func
is implemented by func_int, func_str and co, which also helps debugging.

>> Making generic functions work with ABCs sounds like a requirement to me
> Yes, I will implement that.

Great!

>> Question: what happens if two functions (say in two different modules)
>> are registered for the same type?
> Last one wins. Just like with assigning names in a scope, defining methods
> in a class or overriding them in a subclass.

Works for me.

Cheers
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 409 and the stdlib

2013-05-23 Thread Steven D'Aprano

On 24/05/13 00:24, Ethan Furman wrote:


Here's the code that existed at one point:

 for c in s:
 val = _b32rev.get(c)
 if val is None:
 raise TypeError('Non-base32 digit found')

Even though there is no KeyError to convert in this incarnation, providing the 
cause of failure is still appreciated by the user who's trying to figure out 
what, exactly, went wrong.


For the record, that is the implementation used in Python 3.3.0rc3, so "at some 
point" is actually very recently.


--
Steven
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread Steven D'Aprano

On 24/05/13 01:04, Ethan Furman wrote:

On 05/23/2013 07:58 AM, Łukasz Langa wrote:



I feel that the PEP should explicitly allow or disallow for the
implementation to accept dispatch on annotations, e.g.:

@func.register
def _(arg: int):
   ...

versus

@func.register(int)
def _(arg):
   ...


If the stdlib is still staying out of the annotation business, then it should 
not be allowed.



Perhaps it is time to relax that ruling? The standard library acts as a guide 
to best practice in Python, and I think that uptake of annotations has been 
hurt due to the lack of good examples. Also, anyone with the conceit that their 
library or module may someday be in the standard library cannot afford to use 
annotations at all.

So I'm tentatively +1 on allowing the annotation form in addition to the 
decorator argument form.




--
Steven
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread Steven D'Aprano

On 24/05/13 02:56, Paul Moore wrote:

On 23 May 2013 17:00, Walter Dörwald  wrote:


Should it be possible to register multiple types for the generic function
with one register() call, i.e. should:

@fun.register(int, float)
def _(arg, verbose=False):
   ...

be allowed as a synonym for

@fun.register(int)
@fun.register(float)
def _(arg, verbose=False):



No, because people will misread register(int, float) as meaning first
argument int, second float. The double decorator is explicit as to what is
going on, and isn't too hard to read or write.


I don't think that they will. Being able to register multiple types with a single call 
reads very naturally to me, while multiple decorators still looks weird. Even after many 
years of seeing them, I still get a momentary "What the hell...?" moment when I 
see two decorators on one function. That's only going to be increased when both 
decorators are the same (apart from the argument). The double decorator form above looks 
to me as weird as:

x = func(a)
x = func(b)


would. I have to stop and think about what is going on, and whether or not it 
is a mistake.


So I am a strong +1 on allowing multiple types to be registered in one call.


--
Steven
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread Ben Hoyt
> So I am a strong +1 on allowing multiple types to be registered in one call.

Yeah, agreed. It also fits the pattern set by isinstance(), which
allows a tuple of types, like isinstance(x, (int, str)).

That said, I'm +0 on this PEP itself. It seems no one has provided
decent use-case examples (apart from contrived ones), from the stdlib
for example. In the fairly large codebase I work on, it'd only be used
in one place, and even there the PEP's approach is arguably too simple
for what we're doing. It seems to me for the few times this would be
used, direct and simple use of isinstance() would be clearer. But
maybe that's just our particular codebase.

-Ben
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread PJ Eby
On Thu, May 23, 2013 at 6:58 PM, Ben Hoyt  wrote:
> It seems no one has provided
> decent use-case examples (apart from contrived ones)

Um, copy.copy(), pprint.pprint(), a bunch of functions in pkgutil
which are actually *based on this implementation already* and have
been since Python 2.5...  I don't see how any of those are contrived
examples.  If we'd had this in already, all the registration-based
functions for copying, pickling, etc. would likely have been
implemented this way, and the motivating example for the PEP is the
coming refactoring of pprint.pprint.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread Ethan Furman

On 05/23/2013 02:02 PM, Ronan Lamy wrote:

2013/5/23 Łukasz Langa mailto:luk...@langa.pl>>

On 23 maj 2013, at 20:13, Éric Araujo mailto:mer...@netwok.org>> wrote:

> Question: what happens if two functions (say in two different modules)
> are registered for the same type?

Last one wins. Just like with assigning names in a scope, defining methods
in a class or overriding them in a subclass.


This is a serious annoyance, considering that there are several places where a 
large library can reasonably define the
implementations (i.e. with the class, with the function, or in some utility 
module). Note that in contrast with the case
of functions in a module or methods in a class, linting tools cannot be 
expected to detect a duplication between
functions with different names defined in different modules.


What would you suggest happen in this case?

--
~Ethan~
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread Eric Snow
On May 23, 2013 4:37 PM, "Steven D'Aprano"  wrote:
>
> On 24/05/13 01:04, Ethan Furman wrote:
>> If the stdlib is still staying out of the annotation business, then it
should not be allowed.
>
>
>
> Perhaps it is time to relax that ruling? The standard library acts as a
guide to best practice in Python, and I think that uptake of annotations
has been hurt due to the lack of good examples. Also, anyone with the
conceit that their library or module may someday be in the standard library
cannot afford to use annotations at all.

The idea that decorators determine the meaning of annotations (i.e. they
have no meaning without a decorator) really appeals to me.  I don't see the
imperative for this PEP though, but I'm not opposed.  If there were more
discussion and consensus on annotations + decorators I'd be more convinced.

-eric
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread Eric Snow
On Thu, May 23, 2013 at 7:30 PM, Eric Snow  wrote:
> If there were more
> discussion and consensus on annotations + decorators I'd be more convinced.

However, this PEP should not be gated on any such discussion.

-eric
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] What if we didn't have repr?

2013-05-23 Thread Fernando Perez
On Tue, 21 May 2013 06:36:54 -0700, Guido van Rossum wrote:

> Actually changing __str__ or __repr__ is out of the question, best we
> can do is discourage makingbthem different. But adding a protocol for
> pprint (with extra parameters to convey options) is a fair idea. I note
> that Nick sggested to use single-dispatch generic functions for this
> though. Both have pros and cons. Post design ideas to python-ideas
> please, not here!

Just in case you guys find this useful, in IPython we've sort of created 
this kind of 'extended repr protocol', described and illustrated here 
with examples:

http://nbviewer.ipython.org/url/github.com/ipython/ipython/raw/master/
examples/notebooks/Custom%20Display%20Logic.ipynb

It has proven to be widely used in practice.

Cheers,

f

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread Nick Coghlan
On Fri, May 24, 2013 at 11:45 AM, Eric Snow  wrote:
> On Thu, May 23, 2013 at 7:30 PM, Eric Snow  
> wrote:
>> If there were more
>> discussion and consensus on annotations + decorators I'd be more convinced.
>
> However, this PEP should not be gated on any such discussion.

Right, I think the latest update makes the right call by saying "maybe
someday, but not for now".

Cheers,
Nick.

--
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread Nick Coghlan
On Fri, May 24, 2013 at 10:31 AM, PJ Eby  wrote:
> On Thu, May 23, 2013 at 6:58 PM, Ben Hoyt  wrote:
>> It seems no one has provided
>> decent use-case examples (apart from contrived ones)
>
> Um, copy.copy(), pprint.pprint(), a bunch of functions in pkgutil
> which are actually *based on this implementation already* and have
> been since Python 2.5...  I don't see how any of those are contrived
> examples.  If we'd had this in already, all the registration-based
> functions for copying, pickling, etc. would likely have been
> implemented this way, and the motivating example for the PEP is the
> coming refactoring of pprint.pprint.

We should be able to use it to help deal with the "every growing
importer API" problem, too. I know that's technically what pkgutil
already uses it for, but elevating this from "pkgutil implementation
detail" to "official stdlib functionality" should make it easier to
document properly :)

Cheers,
Nick.

--
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread Nick Coghlan
On Fri, May 24, 2013 at 8:40 AM, Steven D'Aprano  wrote:
> I don't think that they will. Being able to register multiple types with a
> single call reads very naturally to me, while multiple decorators still
> looks weird. Even after many years of seeing them, I still get a momentary
> "What the hell...?" moment when I see two decorators on one function. That's
> only going to be increased when both decorators are the same (apart from the
> argument). The double decorator form above looks to me as weird as:
>
> x = func(a)
> x = func(b)
>
>
> would. I have to stop and think about what is going on, and whether or not
> it is a mistake.

The difference is that this idiom quickly becomes familiar and unexceptional:

@fun.register(float)
@fun.register(Decimal)
def fun_floating_point(arg1, arg2):
...

"Oh, OK, 'fun' is a generic function, and we're registering this as
the implementation for floats and Decimals"

By contrast, the following are *always* ambiguous at the point of
definition, as it depends on how fun is defined:

@fun.register(float, Decimal)
def fun_floating_point(arg1, arg2):
...

@fun.register([float, Decimal])
def fun_floating_point(arg1, arg2):
...

Is that multiple dispatch? Or is it registering for single dispatch on
multiple different types?

Sure, we could pick the latter meaning for the standard library, but
existing generic function implementations (cited in the PEP) use the
tuple-of-types notation for multiple dispatch.

By opting for stacking decorators in the PEP and hence the stdlib, we
leave the way clear for 3rd party multi-dispatch libraries to use
multiple type arguments without introducing any ambiguity.

> So I am a strong +1 on allowing multiple types to be registered in one call.

Whereas I'm a strong -1, as the ambiguity problem it would create is
persistent and irreversible, while stacking registration decorators is
just a new idiom to become accustomed to.

Cheers,
Nick.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 443 - Single-dispatch generic functions

2013-05-23 Thread PJ Eby
On Thu, May 23, 2013 at 11:57 PM, Nick Coghlan  wrote:
> We should be able to use it to help deal with the "every growing
> importer API" problem, too. I know that's technically what pkgutil
> already uses it for, but elevating this from "pkgutil implementation
> detail" to "official stdlib functionality" should make it easier to
> document properly :)


Oh, that reminds me.  pprint() is actually an instance of a general
pattern that single dispatch GF's are good for: "visitor pattern"
algorithms.  There's a pretty good write-up on the general issues with
doing visitor pattern stuff in Python, and how single-dispatch GF's
can solve that problem, here:

http://peak.telecommunity.com/DevCenter/VisitorRevisited

The code samples use a somewhat different API from the PEP, but it's
pretty close.  The main issues solved are eliminating monkeypatching
and fixing the inheritance problems that occur when you use
'visit_foo' methods.  One of the samples actually comes from the old
'compiler' package in the stdlib...  which tells you how long ago I
did the write-up.  ;-)
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com