[EMAIL PROTECTED] wrote: > I'm reading about "high order messages" in Ruby by Nat Pryce, and > thinking if it could be util and if so, if it could be done in Python.
Nice sunday afternoon exercise. Yes, you can do this in python. This is based on a relatively naive translation of the ruby version: class HigherOrderMessage(object): def __init__(self,handler): self.handler = handler class Do(HigherOrderMessage): def __HOM__(self, methname, *args): "implement ruby's method_missing idea" try: for e in self.handler: meth = getattr(e, methname) meth(*args) except TypeError: # Handle non-iterator, could be nicer if self.handler is not None: meth = getattr(self.handler, methname) meth(*args) def __getattribute__(self, methname): try: return super(Do,self).__getattribute__(methname) except AttributeError: def myHom(*args): return self.__HOM__(methname, *args) return myHom class Where(HigherOrderMessage): def __HOM__(self, methname, *args): "implement ruby's method_missing idea" try: r = List() for e in self.handler: meth = getattr(e, methname) if meth(*args): r.append(e) return r except TypeError: r = List() if self.handler is not None: meth = getattr(self.handler, methname) if meth(*args): r.append(self.handler) return r # def __getattribute__(self, methname): "Probably belongs in the baseclass" try: return super(Where,self).__getattribute__(methname) except AttributeError: def myHom(*args): return self.__HOM__(methname, *args) return myHom class enumerable(object): def do(self): return Do(self) def where(self): return Where(self) class List(enumerable,list): "List using enumerable as a mixin" class Claimant(enumerable): def __init__(self, name, age, gender): self.name = name self.age = age self.gender = gender self.benefits = 0 def retired(self): return (self.gender == "male" and self.age >= 65) or \ (self.gender == "female" and self.age >= 60) def receive_benefit(self,amount): self.benefits = self.benefits + amount def __str__(self): return "%s,%s age: %s benefits: %s" % ( self.name, self.gender, str(self.age), str(self.benefits) ) # # Create an enumerable list capable of responding to # claimants = List([ # Just a list which is enumerable as well Claimant("tom", 32, "male"), Claimant("dick", 64, "male"), Claimant("harry", 128, "male"), Claimant("Ivanova", 32, "female"), Claimant("Kochansky", 64, "female"), Claimant("Sung", 128, "female"), ]) # First the normal python way I prefer this) for claimant in claimants: if claimant.retired(): claimant.receive_benefit(50) # Display the results for claimant in claimants: print str(claimant) print # The more direct translation of : # claimants.select {|e| e.retired?}.each {|e| e.receive_benefit 50} [ e.receive_benefit(50) for e in claimants if e.retired() ] # Display the results for claimant in claimants: print str(claimant) print # The single claimant version of the higher order message approach # re-uses the last claimant from above. This one unconditionally # grants benefits. # claimant.do().receive_benefit(50) print claimant print # Iterating over a bunch of Claimants with the higher order message # approach. This conditionally updates the claimaints claimants.where().retired().do().receive_benefit(50) # display results for claimant in claimants: print str(claimant) I'm not convinced I'd actually *use* this approach(*), but it does show that you can certainly take this approach in python. It's certainly interesting though. (*) Largely because there's a bunch of magic happening as far as the user (next programmer to edit the file) is concerned. After all you can't find the definition of retried in "where" or "claimant"; you can't find the definition of "receive_benefit" in "do", "retired", "where" or "claimants". I'm also pretty sure there's other things you'd want to do more than the above generally speaking if you wanted to handle inheritance/etc nicely. (That does make me wonder as well if you'd need to do more in ruby as well) However, this certainly isn't a case of "ruby can do this, and python can't", because clearly python CAN do it :-) Regards, Michael -- http://mail.python.org/mailman/listinfo/python-list