2013-07-11 14 views
7

Dlaczego ponowne otwarcie modułu zagnieżdżonego daje różne wyniki w zależności od użytej składni? Na przykład, to działa prawidłowo:Ponownie otwarta anomalia modułu zagnieżdżonego w Ruby

module A 
    module E 
    end 
end 
module A 
    module E 
    def E.e 
    end 
    end 
end 

Ale:

module A 
    module E 
    end 
end 
module A::E 
    def E.e 
    end 
end 

daje błąd:

reopen.rb:6:in `<module:E>': uninitialized constant A::E::E (NameError) 
from reopen.rb:5:in `<main>' 

(Zanim ktoś zwraca na to uwagę, obejście tego problemu jest użycie self zamiast nazwa modułu podczas definiowania Ee, ale tak naprawdę nie chodzi o to stanowisko.)

+2

O co więc chodzi? –

+0

Punkt targowy - zmieniony. –

Odpowiedz

4

The module słowo kluczowe ustawia kontekst przestrzeni nazw, który jest sprawdzany w odniesieniu do istniejących nazw modułów. Te przestrzenie nazw są następnie przeszukiwane wewnętrznie i zewnętrznie, aby rozwiązać odniesienia do nazw modułów (i klasy).

W pierwszym przykładzie to wygląda jak może trzeba zdefiniować E.e wewnątrz module E bloku, ale w rzeczywistości nie robić:

module A 
    module E 
    end 
end 
module A 
    def E.e 
    end 
end 

Co dzieje się w obu swoich przykładów jest to, że patrzy na Ruby bieżący obszar nazw i próbuje <namespace>::E jako nazwę modułu. W obu przykładach pierwszą rzeczą, którą sprawdza, jest w rzeczywistości A::E::E, która nie istnieje. Następnie wraca do następnego kontekstu. I tutaj przykłady różnią się: W pierwszym przykładzie jest to A::E, który jest ważny, w drugim przykładzie jest to tylko E, który nie jest. Błąd, który następnie rzuca odnosi się do pierwszego sprawdzonego imienia.

+1

Interesujące. IMO 'moduł A :: E' tworząc niepolakierowany kontekst z" zagnieżdżoną "nazwą jest błędem. Jeśli był on równoważny: 'moduł A moduł E ...' Powiedziałbym, że byłby znacznie bliższy normalnej intuicji dotyczącej przestrzeni nazw. –

+0

Tak, zawsze tworzy pojedynczy kontekst w bloku 'module'. Jest przynajmniej samowystarczalny pod tym względem. Nie widzę powodu, dla którego nie można by go uruchomić w inny sposób, z wyjątkiem przyczyn historycznych - może istnieć nawet kod, który opiera się na bieżącym zachowaniu - gdzie zdefiniowane są 'E' i' A :: E' na przykład. –

+0

Wystarczająco fair. Być może podniesienie tego problemu może spowodować jego przeniknięcie do przyszłej wersji Rubiego. –