Re: [Python-Dev] PEP 443 - Single-dispatch generic functions
On Thu, 23 May 2013 12:12:26 +1000 Nick Coghlan ncogh...@gmail.com wrote: On Thu, May 23, 2013 at 10:14 AM, Glenn Linderman v+pyt...@g.nevcal.com wrote: Yet about half of the operator overloads would be incomplete if there were not corresponding __r*__ methods (__radd__, __rsub__, etc.) because the second parameter is as key to the dispatch as the first. While unary operators, and one argument functions would be fully covered by single dispatch, it is clear that single dispatch doesn't cover a large collection of useful cases for operator overloading. 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. I guess you can also reduce every function of several arguments to a function accepting a single tuple of several items, but that doesn't sound very interesting. 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
On Thu, May 23, 2013 at 2:04 AM, Antoine Pitrou solip...@pitrou.net wrote: On Thu, 23 May 2013 12:12:26 +1000 Nick Coghlan ncogh...@gmail.com 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. -- 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/archive%40mail-archive.com
Re: [Python-Dev] PEP 443 - Single-dispatch generic functions
On Thu, 23 May 2013 02:33:57 -0400 Devin Jeanpierre jeanpierr...@gmail.com wrote: On Thu, May 23, 2013 at 2:04 AM, Antoine Pitrou solip...@pitrou.net wrote: On Thu, 23 May 2013 12:12:26 +1000 Nick Coghlan ncogh...@gmail.com 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
Hi, On Thu, May 23, 2013 at 12:33 AM, Łukasz Langa luk...@langa.pl 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
On 23 May 2013 16:37, Devin Jeanpierre jeanpierr...@gmail.com wrote: On Thu, May 23, 2013 at 2:04 AM, Antoine Pitrou solip...@pitrou.net wrote: On Thu, 23 May 2013 12:12:26 +1000 Nick Coghlan ncogh...@gmail.com 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
On 5/23/2013 12:14 AM, Antoine Pitrou wrote: On Thu, 23 May 2013 02:33:57 -0400 Devin Jeanpierrejeanpierr...@gmail.com wrote: On Thu, May 23, 2013 at 2:04 AM, Antoine Pitrousolip...@pitrou.net wrote: On Thu, 23 May 2013 12:12:26 +1000 Nick Coghlanncogh...@gmail.com 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
Le Thu, 23 May 2013 00:31:38 -0700, Glenn Linderman v+pyt...@g.nevcal.com 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
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
On 23 maj 2013, at 01:16, Terry Jan Reedy tjre...@udel.edu 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
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
On 23 maj 2013, at 09:33, Armin Rigo ar...@tunes.org wrote: Hi, On Thu, May 23, 2013 at 12:33 AM, Łukasz Langa luk...@langa.pl 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
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
Ł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
On 23 maj 2013, at 16:49, Guido van Rossum gu...@python.org 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
On 23 May 2013 15:58, Łukasz Langa luk...@langa.pl wrote: On 23 maj 2013, at 16:49, Guido van Rossum gu...@python.org 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
Ok, happy bikeshedding. I'm outta here until that's settled. :-) On Thu, May 23, 2013 at 7:58 AM, Łukasz Langa luk...@langa.pl wrote: On 23 maj 2013, at 16:49, Guido van Rossum gu...@python.org 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
On 05/23/2013 07:58 AM, Łukasz Langa wrote: On 23 maj 2013, at 16:49, Guido van Rossum gu...@python.org 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
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
On 23 May 2013 17:00, Walter Dörwald wal...@livinglogic.de 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
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
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
On Thu, May 23, 2013 at 11:11 AM, Paul Moore p.f.mo...@gmail.com 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
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
On Thu, May 23, 2013 at 2:59 PM, PJ Eby p...@telecommunity.com 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
On 23 maj 2013, at 20:59, PJ Eby p...@telecommunity.com 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
On 23 maj 2013, at 20:13, Éric Araujo mer...@netwok.org 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
On 05/23/2013 01:10 PM, Łukasz Langa wrote: On 23 maj 2013, at 20:59, PJ Eby p...@telecommunity.com 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/5/23 Łukasz Langa luk...@langa.pl On 23 maj 2013, at 20:13, Éric Araujo 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. 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
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
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
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
On 24/05/13 02:56, Paul Moore wrote: On 23 May 2013 17:00, Walter Dörwald wal...@livinglogic.de 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
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
On Thu, May 23, 2013 at 6:58 PM, Ben Hoyt benh...@gmail.com 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
On 05/23/2013 02:02 PM, Ronan Lamy wrote: 2013/5/23 Łukasz Langa luk...@langa.pl mailto:luk...@langa.pl On 23 maj 2013, at 20:13, Éric Araujo mer...@netwok.org 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
On May 23, 2013 4:37 PM, Steven D'Aprano st...@pearwood.info 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
On Thu, May 23, 2013 at 7:30 PM, Eric Snow ericsnowcurren...@gmail.com 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?
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
On Fri, May 24, 2013 at 11:45 AM, Eric Snow ericsnowcurren...@gmail.com wrote: On Thu, May 23, 2013 at 7:30 PM, Eric Snow ericsnowcurren...@gmail.com 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
On Fri, May 24, 2013 at 10:31 AM, PJ Eby p...@telecommunity.com wrote: On Thu, May 23, 2013 at 6:58 PM, Ben Hoyt benh...@gmail.com 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
On Fri, May 24, 2013 at 8:40 AM, Steven D'Aprano st...@pearwood.info 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