Re: [sage-combinat-devel] Re: Do we want a metaclass framework?
On Mon, Apr 23, 2012 at 05:48:10AM -0700, Simon King wrote: ... Our current metaclasses all work by overriding a magical method of type, or adding a magical method to type. Ideally, this should be in a customisable way. In some cases, we want to override not just one method. Currently, each combination of customised methods requires to write a new metaclass. But why not have just *one* metametaclass CustomisationMetaclass, such that CustomisationMetaclass(init,get,reduce) returns a metaclass that allows customisation of three methods? An alternative would be to have a single metaclass, subclass of type, that adds hooks to enable at once all special methods for classes. Pros: - It's simple - It pushes toward eventually having all those hooks directly in type - It is similar to what happens for objects: all hooks are directly available; you just implement those that you need. Inconvenient: - If a class does not use a hook, does it still pay an overhead for the handling of this hook? For most hooks, that's irrelevant: if a class does not use the __classmul__ hook it won't use the syntax A*B either. But a couple of hooks like __classcall__, __classinit__ could slow basic usage. Cheers, Nicolas -- Nicolas M. Thiéry Isil nthi...@users.sf.net http://Nicolas.Thiery.name/ -- You received this message because you are subscribed to the Google Groups sage-combinat-devel group. To post to this group, send email to sage-combinat-devel@googlegroups.com. To unsubscribe from this group, send email to sage-combinat-devel+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sage-combinat-devel?hl=en.
Re: [sage-combinat-devel] Re: Do we want a metaclass framework?
On Mon, Apr 23, 2012 at 05:59:04AM -0700, Simon King wrote: In CustomisationMetaclass, it should not be needed to explicitly state which methods are to be customised. Instead, CustomisationMetaclass should look if it finds a method named __classbla__ and would *automatically* customize type.__bla__. Hence, class MyClass(Parent): __metaclass__ = CustomisationMetaclass @staticmethod def __classadd__(... should suffice. I like this variant because it encapsulates the technical metaclass details. So we can easily change the implementation later on if we change our mind or find a better approach. Cheers, Nicolas -- Nicolas M. Thiéry Isil nthi...@users.sf.net http://Nicolas.Thiery.name/ -- You received this message because you are subscribed to the Google Groups sage-combinat-devel group. To post to this group, send email to sage-combinat-devel@googlegroups.com. To unsubscribe from this group, send email to sage-combinat-devel+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sage-combinat-devel?hl=en.
[sage-combinat-devel] Re: Do we want a metaclass framework?
Hi Nicolas! On 2012-04-24, Nicolas M. Thiery nicolas.thi...@u-psud.fr wrote: On Mon, Apr 23, 2012 at 05:59:04AM -0700, Simon King wrote: Hence, class MyClass(Parent): __metaclass__ = CustomisationMetaclass @staticmethod def __classadd__(... should suffice. I like this variant because it encapsulates the technical metaclass details. So we can easily change the implementation later on if we change our mind or find a better approach. OK. But I think priority should be given to cythonization of the existing metaclasses. Namely, Florent found out how one can produce a cdef'd metaclasses, so that its instances (thus, usual classes) inherit the fast methods (like __call__). One can cdefine NestedClassMetaclass and derive from it a cdefined ClasscallMetaclass (my patch isn't posted yet). Together with some tricks that Florent presented in his original patch at #12808, one should get a considerable speedup in creation of classes. Also I found that one can simply rename sage/structure/dynamic_class.py into sage/structure/dynamic_class.pyx -- that alone should yield some speedup. And then one can likely gain even more from using Cython more properly. But independent of that, I think at some point I will try to produce a cdefined CustomisationMetaclass. *IF* it turns out that it can compete speed-wise, then we can still decide whether we should use it to refactor the existing metaclasses. Best regards, Simon -- You received this message because you are subscribed to the Google Groups sage-combinat-devel group. To post to this group, send email to sage-combinat-devel@googlegroups.com. To unsubscribe from this group, send email to sage-combinat-devel+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sage-combinat-devel?hl=en.
Re: [sage-combinat-devel] Re: Do we want a metaclass framework?
On Tue, Apr 24, 2012 at 07:23:27PM +, Simon King wrote: OK. But I think priority should be given to cythonization of the existing metaclasses. Namely, Florent found out how one can produce a cdef'd metaclasses, so that its instances (thus, usual classes) inherit the fast methods (like __call__). One can cdefine NestedClassMetaclass and derive from it a cdefined ClasscallMetaclass (my patch isn't posted yet). Together with some tricks that Florent presented in his original patch at #12808, one should get a considerable speedup in creation of classes. +1 Also I found that one can simply rename sage/structure/dynamic_class.py into sage/structure/dynamic_class.pyx -- that alone should yield some speedup. And then one can likely gain even more from using Cython more properly. Yes, I have seen that (but see my comment on the ticket) But independent of that, I think at some point I will try to produce a cdefined CustomisationMetaclass. *IF* it turns out that it can compete speed-wise, then we can still decide whether we should use it to refactor the existing metaclasses. +1 Cheers, Nicolas -- Nicolas M. Thiéry Isil nthi...@users.sf.net http://Nicolas.Thiery.name/ -- You received this message because you are subscribed to the Google Groups sage-combinat-devel group. To post to this group, send email to sage-combinat-devel@googlegroups.com. To unsubscribe from this group, send email to sage-combinat-devel+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sage-combinat-devel?hl=en.
[sage-combinat-devel] Re: Do we want a metaclass framework?
Hi Nicolas, On 22 Apr., 00:37, Nicolas M. Thiery nicolas.thi...@u-psud.fr wrote: So the question is how many metaclasses we forsee in the future. Some ideas are below. NestedClassMetaclass is really a workaround for a mishandling of nested classes by Python; Abstractly: What NestedClassMetaclass does is to add an __init__ method, that makes sure that something is done when a new class (i.e., a new instance of NestedClassMetaclass) is created. Of course, other metaclasses could provide other useful __init__ methods. ClasscallMetaclass implements the analogue of special methods but for classes; In particular, it provides a different __call__ method, so that one can customize how an instance of a class created with ClasscallMetaclass is created. DynamicMetaclass is only there for pickling; In particular, it provides __reduce__ for classes that are created with DynamicMetaclass. it's actually fairly similar to ClasscallMetaclass: implementing the special method __reduce__ for a class; we could have a __classreduce__ in type. Indeed. Actually, this could be done for *any* method of `type`, provided we have a framework. We have sage: dir(type) ['__abstractmethods__', '__base__', '__bases__', '__basicsize__', '__call__', '__class__', '__delattr__', '__dict__', '__dictoffset__', '__doc__', '__eq__', '__flags__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__instancecheck__', '__itemsize__', '__le__', '__lt__', '__module__', '__mro__', '__name__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasscheck__', '__subclasses__', '__subclasshook__', '__weakrefoffset__', 'mro'] For each method __bla__, we could have a metaclass ClassblaMetaclass, that overrides __bla__ such that it can be customised with a __classbla__ or __classbla_private__ method defined by the user. We already have ClasscallMetaclass, that overrides __call__, customisable with __classcall__ and __classcall_private__. We have NestedClassMetaclass, that in my scheme should be called ClassinitMetaclass, and is not customisable with __classinit__ yet. We have DynamicMetaclass, which would be ClassreduceMetaclass in my scheme, and you suggest to make it customisable with __classreduce__. There is the abc module: AFAIK, it uses a metaclass overriding __subclasshook__, and in that sense is ClasssubclassMetaclass. Looking at the list above, it would at least make sense to have metaclasses for __new__, perhaps for __instancecheck__, and perhaps also for a combination of __eq__, __le__, ... , __hash__. Then, ClasscallMetaclass also adds a __get__ method (that isn't present in type). Actually I wonder why this is not moved to NestedClassMetaclass, because the example from the documentation pretty much looks like an application of NestedClass and not of Classcall. One could think of implementing other special methods, such as __add__: If C1 and C2 are classes with ClassaddMetaclass, then C1+C2 would do something usefull (for example, return a class that has C1 and C2 as bases) SUMMARY: Our current metaclasses all work by overriding a magical method of type, or adding a magical method to type. Ideally, this should be in a customisable way. In some cases, we want to override not just one method. Currently, each combination of customised methods requires to write a new metaclass. But why not have just *one* metametaclass CustomisationMetaclass, such that CustomisationMetaclass(init,get,reduce) returns a metaclass that allows customisation of three methods? Syntax example: class MyClass(Parent): __metaclass__ = CustomisationMetaclass(call,init,add) @cached_function def __classcall__(cls, *args,**opts): out = type.__call__(cls, *args, **opts) return out @staticmethod def __classinit__(cls, *args,**opts): globals()[cls.__name__] = cls @staticmethod def __classadd__(cls, other): if cls is other: return cls return type(cls)(cls.__name__+And+other.__name__, (cls,other), {}) The result would be a cached subclass of Parent that injects itself into global namespace (and any subclass of MyClass would do the same), and when adding MyClass to another class then the result would be a common subclass. Cheers, Simon -- You received this message because you are subscribed to the Google Groups sage-combinat-devel group. To post to this group, send email to sage-combinat-devel@googlegroups.com. To unsubscribe from this group, send email to sage-combinat-devel+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sage-combinat-devel?hl=en.
[sage-combinat-devel] Re: Do we want a metaclass framework?
PS: On 23 Apr., 14:48, Simon King simon.k...@uni-jena.de wrote: class MyClass(Parent): __metaclass__ = CustomisationMetaclass(call,init,add) ... @staticmethod def __classadd__(cls, other): if cls is other: return cls return type(cls)(cls.__name__+And+other.__name__, (cls,other), {}) Or even easier: In CustomisationMetaclass, it should not be needed to explicitly state which methods are to be customised. Instead, CustomisationMetaclass should look if it finds a method named __classbla__ and would *automatically* customize type.__bla__. Hence, class MyClass(Parent): __metaclass__ = CustomisationMetaclass @staticmethod def __classadd__(... should suffice. Best regards, Simon -- You received this message because you are subscribed to the Google Groups sage-combinat-devel group. To post to this group, send email to sage-combinat-devel@googlegroups.com. To unsubscribe from this group, send email to sage-combinat-devel+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sage-combinat-devel?hl=en.
Re: [sage-combinat-devel] Re: Do we want a metaclass framework?
On Sat, Apr 21, 2012 at 02:41:26PM +, Simon King wrote: But one could argue that explicit is better than implicit. If we just see a finite number of applications, then explicitly programming these finitely many instances may be easier to understand than a general framework for an infinity of applications. We are on the same line ... So the question is how many metaclasses we forsee in the future. NestedClassMetaclass is really a workaround for a mishandling of nested classes by Python; we could hope that it would eventually become unneeded. ClasscallMetaclass implements the analogue of special methods but for classes; that's fairly natural, and it is thinkable that they would eventually end up in the type class. DynamicMetaclass is only there for pickling; it's actually fairly similar to ClasscallMetaclass: implementing the special method __reduce__ for a class; we could have a __classreduce__ in type. Ok, maybe all of the above is just a dream; still at this point I see no strong rationale for the existence of those three metaclasses (beside that have no practical alternatives at this point) Do you foresee other use cases for metaclasses in Sage? Cheers, Nicolas -- Nicolas M. Thiéry Isil nthi...@users.sf.net http://Nicolas.Thiery.name/ -- You received this message because you are subscribed to the Google Groups sage-combinat-devel group. To post to this group, send email to sage-combinat-devel@googlegroups.com. To unsubscribe from this group, send email to sage-combinat-devel+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sage-combinat-devel?hl=en.
[sage-combinat-devel] Re: Do we want a metaclass framework?
Hi Nicolas, On 2012-04-21, Nicolas M. Thiery nicolas.thi...@u-psud.fr wrote: At the same time, it's getting far enough from the KISS principle to get me uncomfortable. Isn't the use of meta-meta classes overkill (and thus potentially fragile, if we are not sure of a Python/Cython rock solid support) for the problem at hand? That's a reasonable question. One could argue that all what my proof-of-concept does is to do automatically/implicitly what is currently done explicitly anyway: Currently, we have to mix NestedClassMetaclass and ClasscallMetaclass (by deriving the latter from the former) and to mix DynamicClassMetaclass and ClasscallMetaclass by creating DynamicClasscallMetaclass (which is derived from both). My framework does the same. From that perspective, dynamic metaclasses make programming easier (it is not needed to make definitions explicitly), in the same sense as dynamic classes (Rings().parent_class) make programming easier. But one could argue that explicit is better than implicit. If we just see a finite number of applications, then explicitly programming these finitely many instances may be easier to understand than a general framework for an infinity of applications. Best regards, Simon -- You received this message because you are subscribed to the Google Groups sage-combinat-devel group. To post to this group, send email to sage-combinat-devel@googlegroups.com. To unsubscribe from this group, send email to sage-combinat-devel+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sage-combinat-devel?hl=en.