Hi Travis, On 2013-05-02, Travis Scrimshaw <tsc...@ucdavis.edu> wrote: > I don't think so... This would be useful for other mutable things such > as matrices and simplicial complex rather than explicitly check it in the > methods themselves.
OK. Thanks to sage.misc.decorators.sage_wraps, it will be easy to create such decorator. Or two decorators: The first complains if the instance is mutable (can be used on __hash__), the second complains if the instance is immutable (can be used on a mutating method). I suggest the name "@invariant" for the first and "@mutabor" (this is Latin for "I will be changed") for the second decorator. Here is a more extreme idea. Since the decorated methods can be overridden in subclasses, I thought of using a metaclass. The following syntax could be made work: class A: __metaclass__ = MutabilityType(['bla'],['__hash__']) def __init__(self, val): self._m = val def bla(self, new_val): self._m = new_val def __hash__(self): return hash(self._m) sage: type(A) __main__.MutabilityMetaclass(mutations=('bla',), invariants=('__hash__',)) sage: a = A(5) The semantics behind this syntax is: - The metaclass provides the new class with methods is_mutable, is_immutable and set_mutability: sage: a.is_mutable() True sage: a.set_mutability(False) sage: a.is_mutable() False - The metaclass ensures that instances of the new class must be mutable for calling the method bla: sage: a.bla(6) Traceback (most recent call last): ... AssertionError: <class '__main__.A'> instance is immutable, <function bla at 0x5274488> must not be called - The metaclass ensures that instances of the new class must be immutable for calling the hash: age: hash(a) 5 sage: a.set_mutability(True) sage: hash(a) Traceback (most recent call last): ... AssertionError: <class '__main__.A'> instance is mutable, <function __hash__ at 0x52746e0> must not be called - Subclasses inherit this behaviour: class B(A): def bla(self, new_val): print "overridden" self._m = new_val def __hash__(self): print "overridden" return hash(self._m) sage: b = B(5) sage: hash(b) Traceback (most recent call last): ... AssertionError: <class '__main__.B'> instance is mutable, <function __hash__ at 0x548e938> must not be called sage: b.set_mutability(False) sage: hash(b) overridden 5 sage: type(B) __main__.MutabilityMetaclass(mutations=('bla',), invariants=('__hash__',)) So, the advantage over a decorator is that the behaviour wrt. mutability is inherited by subclasses, and that the class A (or B) can actually tell exactly which methods are required to be mutable or immutable. The disadvantage is that metaclasses tend to confuse people, and it would be difficult to make it cooperate with existing metaclasses (such as the one used by UniqueRepresentation). This could be implemented by using meta-metaclasses, that create cooperating metaclasses dynamically... What do people think? [ ] @invariant and @mutabor is fine [ ] these (meta-)metaclasses are totally crazy [ ] others [please elaborate] Best regards, Simon -- You received this message because you are subscribed to the Google Groups "sage-devel" group. To unsubscribe from this group and stop receiving emails from it, send an email to sage-devel+unsubscr...@googlegroups.com. To post to this group, send email to sage-devel@googlegroups.com. Visit this group at http://groups.google.com/group/sage-devel?hl=en. For more options, visit https://groups.google.com/groups/opt_out.