On 11/22/06, Phillip J. Eby <[EMAIL PROTECTED]> wrote: > The defop statement (and its decorators if any) would translate to this code: > > @<decorators> > def <anonfunc>(<args>): > <suite> > > addmethod(<expr>, <anonfunc>, enclosing_class_or_None)
Where is it gonna get the enclosing class? That object hasn't been created yet at the time defop executes. > In other words, addmethod() is invoked following completion of the class > suite (if there is one), and passed the decorated anonymous function object. > Now, we could say that addmethod() just calls expr.__addmethod__. This > would work as long as each builtin had its own __addmethod__() that did the > 'cls.__special__ = method' work. OK, this I can understand. Thanks for being concrete. > However, I personally find it easier to just think of addmethod() as a > generic function, yes, but that's you've had generic functions on your brain for a year or more now. For the rest of us, saying "it calls expr.__addmethod__" is a lot easier to process. And you've already shown earlier that these two are pretty much equivalent. :-) > so that you can define methods for it that recognize the > builtin generics and do the right thing. This also doesn't require the > builtins to grow new methods, and thus can be implemented in today's Python > using only Python code. (Like the example that you described as > brain-exploding orange smoke, which was an actual implementation of > addmethod that would work in today's Python 2.x) Working code can explode heads too. :-) > But if it's easier for you to conceptualize, let's just say it expects expr > to have an __addmethod__ method. Yes, thank you, this helps. > An implementation for today's Python: > > from peak.util.decorators import decorate_class > > def defop(expr): > def decorate(func): > def do_add(cls): > addmethod(expr, func, cls) > return cls > try: > decorate_class(do_add) > except SyntaxError: # not in a class > do_add(None) # handle top-level function > return decorate Alas, this is all smoke and mirrors again for me, since I don't know what decorate_class does, or why on earth it would raise SyntaxError. How does this address the problem that the class doesn't yet exist? > (The 'decorate_class' function applies its argument as a class decorator > for the class its caller is invoked from. This is the same mechanism (and > actual code!) that Zope uses to do in-body class decorators like > 'implements()'.) decorate_class raises a SyntaxError if its caller is not > being run directly inside a class body. That's a bizarre use of that exception. I'm guessing that decorate_class squirrels away some info for later? Everything here seems designed to hide the implementation details, which is great for actual use, but kills understanding of the mechanism. :-( > And yes, this uses frame magic, and no, it's not fragile, as it knows the > difference between class and non-class frames. Wow. How can you tell? Does it work with Jython, IronPython and PyPy? I still find it fragile somehow -- or at least severely hackish. I like the other proposal (where it puts a special attribute on the function object which is then found by the type) better, it doesn't require sys._getframe(). > The implementation has been > in Zope for a good few years now, likewise Twisted and PEAK. It's also > available as a standalone package from: > > http://cheeseshop.python.org/pypi/DecoratorTools > > > >but how on earth is the defop syntax of the @defop decorator going to > >generate this? > > @defop(flattening.flatten) > def flatten_btree(bt:BinaryTree): > # ... do stuff to bt I'm assuming that's outside the context of the BinaryTree class -- since inside it, Binarytree is undefined. > Of course, this assumes that flattening.flatten.__addmethod__() is smart > enough to pull the type information off the first argument, if the third > addmethod() argument is None. Assuming we have optional argument annotations that would be nice. > >A different line of questioning would be to try to understand how > >Phillip's addmethod and hasmethod are supposed to work. I still hope > >someone will explain it to me. > > addmethod registers a method with a generic function. The only reason we > even need it as a separate function (as opposed to just assuming a > __hasmethod__) is to allow retrofitting of existing Python objects (such as > iter/len/etc.) as generic functions via __special__ method setting. The > same applies to hasmethod vs. just using __contains__ or something of that > sort. Hm, I think this is the first time in this thread that you meant to use 'iter', 'len' etc. as "tokens". I think I'd rather change them a bit so that they can be objects that actually understand __addmethod__ and __hasmethod__. > If you want to treat it as a Py3K only thing I do, that's why we're discussing it here. > and have __hasmethod__ and > __addmethod__ slots for builtin functions, I have no problem with making those builtins that are generic functions into instances of some other class. I don't think all 50+ builtins should become generic methods. > then there's no need to have > actual addmethod/hasmethod functions. But that's sort of like saying we > don't need getattr() any more because we can just use > type(ob).__getattribute__() now! :) But I think you're really proposing an addmethod builtin that calls an __addmethod__ method, right? That sounds fine to me if we can work out the rest of the details. -- --Guido van Rossum (home page: http://www.python.org/~guido/) _______________________________________________ Python-3000 mailing list [email protected] http://mail.python.org/mailman/listinfo/python-3000 Unsubscribe: http://mail.python.org/mailman/options/python-3000/archive%40mail-archive.com
