Dans les langages dynamiques orientés-objets tels que Ruby, Python ou Smalltalk, on dispose à la fois des concepts de classes et d'objets permettant la réalisation de mécanismes d'aiguillage dynamique, et de la notion de fermeture, ou lambda-abstraction, ou bloc, qui permet de modifier dynamiquement la définition de méthodes et de fonctions et leur utilisation comme valeurs de première classe.

Ces mécanismes combinés permettent d'obtenir un Visiteur plus simple, plus élégant et plus compact.

Le code du visiteur (ici, l'exemple de l'évaluateur) fait apparaître ces manipulations dynamiques. Chacune des méthodes visit_xxx fait référence à la méthode visit(self, node) qui utilise une table associative (dispatch) permettant de sélectionner une méthode à partir de l'identifiant du type récupéré dynamiquement (type(node)).




class ExpressionEvaluator(object):
    """Documentation for ExpressionEvaluator"""


    def __init__(self):
        super(ExpressionEvaluatorself).__init__()


    def visit_binary(selfnodeop):
        return op(self.visit(node.left), self.visit(node.right))


    def visit_and(selfnode):
        return self.visit_binary(nodelambda xy: x + y)


    def visit_sub(selfnode):
        return self.visit_binary(nodelambda xy: x - y)


    def visit_mul(selfnode):
        return self.visit_binary(nodelambda xy: x * y)


    def visit_div(selfnode):
        return self.visit_binary(nodelambda xy: x / y)


    def visit_literal(selfnode):
        return node.value


    dispatch = {
        And: visit_and,
        Sub: visit_sub,
        Mul: visit_mul,
        Div: visit_div,
        Literal: visit_literal
        }


    def visit(selfnode):
        return self.dispatch[type(node)](selfnode)
© 2006

\Nouveau et intéressant