Fun with decorators and unification dispatch

talin at acm dot org viridia at gmail.com
Sat Sep 10 20:51:53 EDT 2005


Yes, it was a typo.

Even thought the function has not yet been bound to the name
"Factorial" when it calls the decorator, the function's __name__
attribute is set to it, so I use that to look up the name of the
generic.

Here''s the source for Arity:

def Arity( *pattern ):
    """A function decorator that defines a specific arity of a generic
function. This registers the
    specific implementation with the generic function (which must be in
the global scope.)"""

    def inner( f ):
        if isinstance( f, Function ):
            generic = f
            f = generic.last_defined
        else:
            name = f.__name__
            if not name in f.func_globals:
                raise Exception( "Generic function " + name + " has not
been defined." )
            generic = f.func_globals[ name ]
            generic.name = name
            generic.last_defined = f
        generic.add_arity( pattern, f )
        return generic
    return inner

There's a couple of kludges here:

1) The Generic doesn't know its own name until you define at least one
specialization for it. Otherwise, you would have to say:

Factorial = Function( "Factorial" )

which I consider verbose and redundant.

2) The whole last_defined thing is to allow multiple arities for a
single specialized function. Since the arity normally returns the
generic, and not the specialized func, as the return value, that means
that any additional decorators will be applied to the generic rather
than the specialized func. last_defined is a kludge for getting around
that, but only for decorators that understand the situation.




More information about the Python-list mailing list