2016-01-07 22 views
6

chiamate metodo possono generalmente omettere il ricevitore e le parentesi per gli argomenti:Perché una chiamata al metodo deve essere disambiguita quando in linea di principio può essere una costante?

def foo; "foo" end 
foo # => "foo" 

Nel caso precedente, foo è ambigua tra il metodo di chiamata e riferimento ad un potenziale variabile locale. In assenza di quest'ultimo, viene interpretato come una chiamata al metodo.

Tuttavia, quando il nome del metodo può in linea di principio essere un nome costante (vale a dire, quando inizia con una lettera maiuscola e consiste solo di lettere), sembra che sia necessario chiarire le ambiguità.

def Foo; "Foo" end 
Foo # => NameError: uninitialized constant Foo 
Foo() # => "Foo" 
self.Foo # => "Foo" 

Perché è questo il caso? Perché una chiamata al metodo deve essere esplicitamente distinta da un riferimento a una costante anche in assenza di una costante con lo stesso nome?

risposta

5

L'insieme di variabili locali che è portata in un qualsiasi punto del programma è definita lessicale e possono quindi essere determinati staticamente, anche se già nel tempo di analisi. Quindi, Ruby sa già prima del runtime quali variabili locali sono in ambito e può quindi distinguere tra un invio di messaggi e una dereferenziazione di variabili locali.

Le costanti vengono cercate prima in modo lessicale, ma poi via ereditarietà, cioè dinamicamente. Non è noto quali costanti siano in ambito prima del runtime. Pertanto, per disambiguare, Ruby assume sempre che sia una costante, a meno che ovviamente non lo sia, cioè prende argomenti o ha un ricevitore o entrambi.

+0

Grazie per la risposta. – sawa

+1

Il fatto che le variabili locali siano definite in fase di analisi è la ragione del comportamento un po 'non intuitivo di "if false then foo = 43 end; foo # => nil (invece di NameError) '. –

+0

@ JörgWMittag Questo ha perfettamente senso. –

0

Fai una bella domanda. Come dici tu, Ruby vuole trattarlo come una costante e quindi fare una ricerca costante.

Il seguente frammento mostra tuttavia il comportamento corrente e quindi modificando const_missing, sembra che si ottenga il comportamento desiderato. E a dire la verità non riesco a rompere nulla.

La mia conclusione è che questo è stato come qualcuno ha già suggerito, solo una decisione di progettazione, ma è strano perché in generale il rubino favorisce la convenzione contro l'applicazione.

Oppure mi manca qualche caso in cui le cose si confondono e succede la cosa sbagliata.

<script type="text/ruby"> 
 
def puts(s); Element['#output'].html = Element['#output'].html + s.to_s.gsub("\n", "<br/>").gsub(" ", "&nbsp;") + "<br/>"; end 
 

 
class ImAClass 
 
    def self.to_s 
 
    "I am ImAClass Class" 
 
    end 
 
end 
 

 
def ImAMethod 
 
    "hello" 
 
end 
 

 
class DontKnowWhatIAm 
 
    def self.to_s 
 
    "a Class" 
 
    end 
 
end 
 

 
def DontKnowWhatIAm 
 
    "a method" 
 
end 
 

 
puts "ImAClass: #{ImAClass}" 
 

 
begin 
 
    puts "ImAMethod: #{ImAMethod}" 
 
rescue Exception => e 
 
    puts "confusion! #{e.message}" 
 
end 
 

 
puts "ImAMethod(): #{ImAMethod()}" 
 

 
puts "DontKnowWhatIAm: #{DontKnowWhatIAm}" 
 

 
puts "DontKnowWhatIAm(): #{DontKnowWhatIAm()}" 
 

 
class Module 
 
    alias_method :old_const_missing, :const_missing 
 
    def const_missing(c) 
 
    if self.respond_to? c 
 
     self.send c 
 
    else 
 
     old_const_missing(c) 
 
    end 
 
    end 
 
end 
 

 
class Foo 
 
    def self.Bar 
 
    "im at the bar" 
 
    end 
 
end 
 

 
puts "now we can just say: Foo::Bar and it works! #{Foo::Bar}" 
 
    
 
</script> 
 

 

 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<script src="https://rawgit.com/reactive-ruby/inline-reactive-ruby/master/inline-reactive-ruby.js"></script> 
 
<div id="output" style="font-family: courier"></div>

2

Non c'è una grande ragione dietro la differenza. Volevo solo che foo si comportasse come foo(), se non ci sono variabili locali foo nell'oscilloscopio. Ho pensato che fosse utile per creare DSL ecc. Ma non vedevo alcun motivo per fare in modo che Foo si comportasse come Foo().

+4

Che sorpresa!本 物 の 松本 さ ん で す か. – sawa