2013-07-11 10 views
7

Perché la riapertura di un modulo nidificato produce risultati diversi a seconda della sintassi utilizzata? Per esempio, questo funziona bene:Anomalia modulo nidificata riaperta in Ruby

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

Ma questo:

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

dà l'errore:

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

(Prima che qualcuno fa questo, una soluzione è quello di utilizzare self invece di il nome del modulo quando si definisce Ee, ma non è proprio questo il punto di questo post.)

+2

Quindi, qual è la domanda? –

+0

Punto giusto - riformulato. –

risposta

4

La parola chiaveimposta un contesto dello spazio dei nomi controllato per i riferimenti ai nomi esistenti dei moduli. Questi spazi dei nomi vengono quindi ricercati dall'interno all'esterno per risolvere i riferimenti ai nomi dei moduli (e della classe).

Nel tuo primo esempio, sembra come potrebbe essere necessario definire E.e all'interno module E blocco, ma in realtà non lo fai:

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

Cosa succede in entrambi i tuoi esempi è che Ruby guarda lo spazio dei nomi corrente e prova <namespace>::E come nome del modulo. Quindi, in entrambi gli esempi, la prima cosa che controlla è infatti A::E::E che non esiste. Quindi torna al prossimo contesto. Che è dove gli esempi differiscono: Nel primo esempio è A::E che è valido, nel secondo esempio, è solo E che non lo è. L'errore che genera poi si riferisce al nome che ha controllato.

+1

Interessante. Il modulo IMO 'A :: E' che crea un contesto non annidato con un nome" annidato "è un bug. Se fosse equivalente a: 'modulo A modulo E ...' Direi che sarebbe molto più vicino alla normale intuizione sui namespace. –

+0

Sì, crea sempre un singolo contesto, all'interno del blocco 'module'. È almeno auto-consistente in questo senso. Non riesco a vedere alcun motivo per cui non possa essere fatto funzionare in un altro modo, tranne che per ragioni storiche - potrebbe anche esserci del codice là fuori che si basa sul comportamento corrente - dove 'E' e' A :: E' sono entrambi definiti per esempio. –

+0

Abbastanza giusto. Forse sollevare il problema qui potrebbe farla passare in una versione futura di Ruby. –