2011-06-28 3 views
2

Je travaille sur un DSL assez simple et j'aimerais déclarer et allouer des variables plus naturellement.Comment créer une allocation variable naturelle

GlobalMemory.init { 
    val1 5 
    val2 "some string" 
} 

Ceci est pour une machine virtuelle simple qui exécute le DSL. Cela fonctionne très bien pour ce code

class GlobalMemory 
    include Singleton 

    def self.init &blk 
    GlobalMemory.instance.allocate &blk 
    end 

    def method_missing sym,*args, &blk 
    @segments[sym]=args[0] 
    end 

    def allocate &blk 
    self.instance_eval &blk 
    end 
end 

Y at-il un moyen de permettre val1=5(and val1 = 5)? Lorsque j'essaie cela, method_missing ne se déclenche pas et aucun message d'erreur ne se produit.

Répondre

1

Il fonctionnera comme-est, si vous faites quelque chose comme:

GlobalMemory.init { 
    self.val3 = 'value' 
} 

Sinon, il est impossible de distinguer une déclaration variable locale. Je suppose que la plus belle façon de le faire serait d'avoir un paramètre de bloc et d'écrire votre méthode init comme ceci:

GlobalMemory.init { |g| 
    g.val1 5 
    g.val2 "some string" 
    g.val3 = 'yeah' 
} 

Je foiré un peu avec essayer d'obtenir la var1 = solution de travail en utilisant #local_variables, mais le le plus proche que je pourrais venir est ceci:

class Foo 
    def initialize(&bl) 
     @data = {} 
     b = yield self 
     still_to_assign = eval('local_variables', b) - eval('local_variables', bl) 
     still_to_assign.each { |v| r = eval(v,b); @data[v] = r } 
    end 
end 

Foo.new { 
    one = 1 
    two = 2 
    three = 3 
    binding 
} 

Comme vous pouvez le voir, il vous faut retourner un objet de liaison à la fin de votre bloc. Il a également quelques problèmes avec les variables qui ont déjà été déclarées avant le bloc. Peut-être que quelqu'un peut suggérer une meilleure façon de le faire?

1

Je ne pense pas qu'il soit possible de le faire proprement comme un DSL interne