2010-06-10 25 views
3

Je travaille sur Pickaxe 1.9, et je suis un peu troublé par la recherche constante dans les blocs instance/class_eval. J'utilise 1.9.2.Ruby: comment la recherche constante fonctionne-t-elle dans instance_eval/class_eval?

Il semble que Ruby gère-recherche constante * blocs _eval de la même manière, il ne méthode recherche:

  1. look pour une définition dans receiver.singleton_class (plus mixins);
  2. puis dans receiver.singleton_class.superclass (plus mixins);
  3. puis continuez l'eigenchain jusqu'à ce que vous arriviez à #<Class:BasicObject>;
  4. dont la superclasse est Class;
  5. puis le reste de la chaîne des ancêtres (y compris Object, qui stocke toutes les constantes que vous définissez au plus haut niveau), la vérification de mixins le long du chemin

Est-ce exact? La discussion de Pickaxe est un peu laconique.

Quelques exemples:

class Foo 
    CONST = 'Foo::CONST' 
    class << self 
    CONST = 'EigenFoo::CONST' 
    end 
end 

Foo.instance_eval { CONST } # => 'EigenFoo::CONST' 
Foo.class_eval { CONST } # => 'EigenFoo::CONST', not 'Foo::CONST'! 
Foo.new.instance_eval { CONST } # => 'Foo::CONST' 

Dans l'exemple class_eval, Foo-la-classe n'est pas un arrêt le long de la chaîne des ancêtres de Foo-the-objet!

Et un exemple avec mixins:

module M 
    CONST = "M::CONST" 
end 
module N 
    CONST = "N::CONST" 
end 

class A 
    include M 
    extend N 
end 

A.instance_eval { CONST } # => "N::CONST", because N is mixed into A's eigenclass 
A.class_eval { CONST } # => "N::CONST", ditto 
A.new.instance_eval { CONST } # => "M::CONST", because A.new.class, A, mixes in M 

Répondre

1

Dans la recherche constante 1.9.2 a changé à nouveau pour être équivalent au comportement 1.8.7.

class A 
    class B 
    class C 
    end 
    end 
end 

A.class_eval { B } # => NameError 
A.instance_eval { B } # => NameError 
A.new.instance_eval { B } # => A::B 

Fondamentalement, les constantes ont une portée quasi-lexicale. Cette USED à être différente entre les branches 1.9.x et 1.8.x, et il a fait de la compatibilité croisée de la bibliothèque une douleur, alors ils l'ont changé.

Yehuda Katz's (successful) appeal to restore 1.8 behavior

+0

Remarque: À partir de Ruby 2.3, ce n'est plus vrai. – sawa

0

Constantes sont effectivement scope afin que vous lexicalement ne pouvez pas y accéder sténo en dehors de la hiérarchie du module dans lequel ils sont définis. Il y a une bonne explication here et légèrement hors sujet mais une bonne lecture here.