[Python-3000] PEP 3124 - more commentary (original) (raw)
Guido van Rossum guido at python.org
Tue May 15 02:17:57 CEST 2007
- Previous message: [Python-3000] PEP 3124 - more commentary
- Next message: [Python-3000] PEP 3124 - more commentary
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
On 5/14/07, Phillip J. Eby <pje at telecommunity.com> wrote:
At 03:43 PM 5/14/2007 -0700, Guido van Rossum wrote: > > Chaining using the first argument can be implemented using a bound > > method object, which gets performance bonuses from the C eval loop > > that partial() objects don't. (Of course, when RuleDispatch was > > written, partial() objects didn't exist, anyway.) > >Sounds like premature optimization to me. We can find a way to do it >fast later; let's first make it right.
As I said, when RuleDispatch was written, partial() didn't exist; it was less a matter of performance there than convenience.
>True. So are you working with Tim Delaney on this? Otherwise he may >propose a simpler mechanism that won't allow this re-use of the >mechanism. PEP 367 doesn't currently propose a mechanism for the actual assignment; I was waiting to see what was proposed, to then suggest as minimal a tweak or generalization as necessary. Also, prior to now, you hadn't commented on the first-argument-class rule and I didn't know if you were going to reject it anyway. >super is going to be a keyword with magic properties. Wouldn't it be >great if instead of > >@when(...) >def flatten(x: Mapping, nm: nextmethod): > ... > nm(x) > >we could write > >@when(...) >def flatten(x: Mapping): > ... > super.flatten(x) # or super(x) > >or some other permutation of super? Well, either we'd have to implement it using a hidden parameter, or give up on the possibility of the same function being added more than once to the same function (e.g., for both Mapping and some specific types). There's no way for the code in the body of the overload to know in what context it was invoked. The current mechanism works by creating bound methods for each registration of the same function object, in each "applicability chain". That doesn't mean it's impossible, just that I haven't given the mechanism any thought, and at first glance it looks really hairy to implement -- even if it were done using a hidden parameter. >Or do you see the need to call >both next-method and super from the same code? Hm, that's a mind-bender. I can't think of a sensible use case for that, though. If you're a plain method, you'd just use super. If you're a generic function or overloaded method, you'd just call the next method. The only way I can see you doing that is if you needed to call the super of some other method, which doesn't make a lot of sense. In any case, we could probably use super(...) for next-method and super.methodname() for everything else, so I wouldn't worry about it. (Which means you'd have to use super.call() inside of a call method, but I think that's OK.) >Do note that e.g. in IronPython (and maybe also in Jython?) >exec/eval/compile are 10-50x slower (relative to the rest of the >system) than in CPython. This would only get done by @overloadable, and never again thereafter. >It does look like a clever approach though. Does that mean you dislike it? ;-) > > Hm. I'll need to give some thought to that, but it seems to me that > > it's sort of like having None defaults for the missing arguments, and > > then treating the missing-argument versions as requiring type(None) > > for those arguments. Except that we'd need something besides None, > > and that the overloads would need wrappers that drop the extra > > arguments. It certainly seems possible, anyway. > > > > I'm not sure I like it, though. > >C++ and Java users use it all the time though. Right, but they don't have keyword arguments or defaults, either. The part I'm not sure about has to do with interaction with Python-specific things like those. When do you use each one? One Obvious Way seems to favor default arguments, especially since you can always use defaults of None and implement overloads for type(None) to catch the default cases. i.e., ISTM that cases like range() are more an exception than the rule. > > It's not obvious from the first > > function's signature that you can call it with fewer arguments, or > > what that would mean. For example, shouldn't the later signatures be > > "range(stop)" and "range(start,stop)"? Hm. > >I don't know if the arg names for overloadings must match those of the >default function or not -- is that specified by your PEP? It isn't currently, but that's because it's assumed that all the methods have the same signature. If we were going to allow subset-signatures (i.e, allow you to define methods whose signature omits portions of the main function's signature), ISTM that the argument names should have meaning. Of course, maybe a motivating example other than "range()" would help here, since not too many other functions have optional positional arguments in the middle of the argument list. :) >My own trivially simple overloading code (sandbox/overload, and now >also added as an experiment to sandbox/abc, with slightly different >terminology and using issubclass exclusively, as you recommended over >a year ago :-) has no problem with this. Of course it only handles >positional arguments and completely ignores argument names except as >keys into the annotations dict. Yeah, none of my GF implementations care about the target methods' signatures except for the nextmethod thingy. But with variable argument lists, I think we should care. Also, AFAIK, the languages that allow different-sized argument lists for the same function either don't have first class functions (e.g. Java) or else have special syntax to allow you to refer to the different variations, e.g. "x/1" and "x/2" to refer to the 1 and 2 argument versions of function x. That is, they really are different objects. (And Java and C++ of course have less comprehensible forms of name mangling internally.) Personally, though, I think that kind of overloading is a poor substitute for the parameter flexibility we already have in Python. That is, I think those other languages should be envying Python here, rather than the other way around. :)
Perhaps. Though C++ does have argument default values.
Other use cases that come to mind are e.g. APIs that you can pass either a Point object or two (or three!) floats. This is not a natural use case for argument default values, and it's not always convenient to require the user to pass a tuple of floats (perhaps the three-floats API already existed and its signature cannot be changed for compatibility reasons). Or think of a networking function that takes either a "host:port" string or a host and port pair; thinking of this as having a default port is also slightly awkward, as you don't know what to do when passed a "host:port" string and a port.
-- --Guido van Rossum (home page: http://www.python.org/~guido/)
- Previous message: [Python-3000] PEP 3124 - more commentary
- Next message: [Python-3000] PEP 3124 - more commentary
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]