Created
December 9, 2011 05:51
-
-
Save cwvh/1450378 to your computer and use it in GitHub Desktop.
Example of asymmetric and symmetric multimethods.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from mm import multimethod, symmultimethod | |
class Ship(object): | |
def __init__(self, name): | |
self.name = name | |
def __str__(self): | |
return self.name | |
class Asteroid(object): | |
def __init__(self, name): | |
self.name = name | |
def __str__(self): | |
return self.name | |
@multimethod(Ship, Asteroid) | |
def damage(ship, asteroid): | |
print '%s did insignificant damage to %s' % (ship, asteroid) | |
@multimethod(Asteroid, Ship) | |
def damage(asteroid, ship): | |
print '%s completely obliterated %s' % (asteroid, ship) | |
@symmultimethod(Ship, Asteroid) | |
def collide(a, b): | |
print 'bang!' | |
if __name__ == '__main__': | |
ship = Ship('Millennium Falcon') | |
asteroid = Asteroid('99942 Apophis') | |
damage(ship, asteroid) | |
damage(asteroid, ship) | |
collide(ship, asteroid) | |
collide(asteroid, ship) | |
# $ python game.py | |
# Millennium Falcon did insignificant damage to 99942 Apophis | |
# 99942 Apophis completely obliterated Millennium Falcon | |
# bang! | |
# bang! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# MultiMethod and multimethod, written by GvR (2005) | |
# http://www.artima.com/weblogs/viewpost.jsp?thread=101605 | |
# | |
# SymmetricMultiMethod and symmultimethod, written by Kay Schluehr (2005) | |
# http://www.artima.com/forums/flat.jsp?forum=106&thread=101605 | |
registry = {} | |
class MultiMethod(object): | |
def __init__(self, name, symmetric=False): | |
self.name = name | |
self.typemap = {} | |
def __call__(self, *args): | |
types = tuple(arg.__class__ for arg in args) | |
function = self.typemap.get(types) | |
if function is None: | |
raise TypeError("no match") | |
return function(*args) | |
def register(self, types, function): | |
if types in self.typemap: | |
raise TypeError("duplicate registration") | |
self.typemap[types] = function | |
class SymmetricMultiMethod(MultiMethod): | |
def __call__(self, *args): | |
types = tuple(sorted(arg.__class__ for arg in args)) | |
function = self.typemap.get(types) | |
if function is None: | |
raise TypeError("no match") | |
return function(*args) | |
def multimethod(*types): | |
def register(function): | |
name = function.__name__ | |
mm = registry.get(name) | |
if mm is None: | |
mm = registry[name] = MultiMethod(name) | |
mm.register(types, function) | |
return mm | |
return register | |
def symmultimethod(*types): | |
def register(function): | |
name = function.__name__ | |
mm = registry.get(name) | |
if mm is None: | |
mm = registry[name] = SymmetricMultiMethod(name) | |
mm.register(tuple(sorted(types)), function) | |
return mm | |
return register |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment