Re: [sage-combinat-devel] Re: Do we want a metaclass framework?

2012-04-24 Thread Nicolas M. Thiery
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?

2012-04-24 Thread Nicolas M. Thiery
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?

2012-04-24 Thread Simon King
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?

2012-04-24 Thread Nicolas M. Thiery
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?

2012-04-23 Thread Simon King
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?

2012-04-23 Thread Simon King
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?

2012-04-22 Thread Nicolas M. Thiery
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?

2012-04-21 Thread Simon King
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.