# HG changeset patch # User aurelien@trantor.local # Date 1266224943 -3600 # Mon Feb 15 10:09:03 2010 +0100 # Node ID af6aa5c67e032633c8d7daee0d92fd4813e8e6a8 # Parent 4318383b091a2847d49ba2d9f3511c4434c6f996 use generators, cleanup & simplify a bit diff --git a/__init__.py b/__init__.py --- a/__init__.py +++ b/__init__.py @@ -9,6 +9,6 @@ gf = _METHS.get(name) if gf is None: gf = _METHS[name] = mm.GF() - gf.add_rule(types, meth) + gf.register(types, meth) return gf return _wrap diff --git a/dispatch.py b/dispatch.py --- a/dispatch.py +++ b/dispatch.py @@ -5,46 +5,38 @@ def lexicographic_mro(signature, matches): "dispatch ranking similar to CLOS" - mros = [klass.mro() for klass in signature] - for (sig,func),i in zip(matches,xrange(1000)): - matches[i] = (map(proximity, sig, mros), matches[i]) - matches.sort(reverse=True) - return map(lambda t:t[1], matches) - -def signature(*args): - return tuple(o.__class__ for o in args) + mros = tuple(klass.mro() for klass in signature) + return sorted((map(proximity, sig, mros), func) + for sig, func in matches) class GF(object): def __init__(self): self._table = [] + self._cache = {} - def add_rule(self, sig, func): - self._table.append((sig, func)) + def register(self, sig, func): + self._table.append((tuple(sig), func)) self._cache = {} def __call__(self, *args): - sig = signature(*args) - self._pos = 0 - if sig not in self._cache: - self._funcs = self.linearized_table(sig) - func = self._funcs.pop() - self._cache[sig] = func - else: - func = self._cache[sig] + sig = tuple(x.__class__ for x in args) + func = self._cache.get(sig) + if func is None: + self._funcs = self.compute_mro(sig) + try: + self._cache[sig] = func = self._funcs.next() + except StopIteration: + raise TypeError('no defined call signature args (%s)' % args) return func(*args) def next_method(self, *args): - func = self._funcs.pop() + func = self._funcs.next() return func(*args) - def linearized_table(self, sig): - table = [(s,f) for s,f in self._table - if len(s) == len(sig) - and reduce(mul, map(issubclass, sig, s))] - if not table: - def nomatch(*a): - raise TypeError('no defined call signature <%s> for args (%s)' % - (','.join([str(o) for o in sig]), a)) - return [nomatch] - return map(lambda l:l[1], lexicographic_mro(sig, table)) + def compute_mro(self, callsig): + siglen = len(callsig) + table = ((sig, func) for sig, func in self._table + if len(sig) == siglen + and reduce(mul, map(issubclass, callsig, sig))) + return (x[1] for x in lexicographic_mro(callsig, table)) diff --git a/test/test_gf.py b/test/test_gf.py --- a/test/test_gf.py +++ b/test/test_gf.py @@ -108,7 +108,7 @@ def foo(b,x): return b,x b, y = B(), Y() - print foo(b, y) + foo(b, y) if __name__ == '__main__': unittest.main()