2016-01-07 8 views
6

Methodenaufrufe können in der Regel den Empfänger und die Klammern für die Argumente wegzulassen:Warum muss ein Methodenaufruf disambiguiert werden, wenn er im Prinzip konstant sein kann?

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

Im obigen Fall ist foo mehrdeutig zwischen Methodenaufruf und Bezugnahme auf eine mögliche lokale Variable. In Ermangelung letzterer wird es als Methodenaufruf interpretiert.

Wenn jedoch der Methodenname im Prinzip ein konstanter Name sein kann (d. H. Wenn er mit einem Großbuchstaben beginnt und nur aus Buchstaben besteht), scheint es eine Disambiguierung zu erfordern.

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

Warum ist das der Fall? Warum muss ein Methodenaufruf explizit von einer Referenz auf eine Konstante unterschieden werden, auch wenn eine Konstante mit demselben Namen fehlt?

Antwort

5

Der Satz von lokalen Variablen, die lexikalisch an jedem beliebigen Punkt im Programm in Rahmen ist festgelegt und somit statisch bestimmt werden kann, auch so früh wie Parse-Zeit. So weiß Ruby schon vor der Laufzeit, welche lokalen Variablen sich im Bereich befinden und kann somit zwischen einer Nachrichtenübertragung und einer lokalen Variablen-Dereferenz unterscheiden.

Konstanten werden zuerst lexikalisch, dann aber über Vererbung, d. H. Dynamisch, nachgeschlagen. Es ist nicht bekannt, welche Konstanten vor der Laufzeit in Reichweite sind. Um dies zu verdeutlichen, nimmt Ruby immer an, dass es eine Konstante ist, es sei denn, es ist offensichtlich nicht, d.h. es braucht Argumente oder hat einen Empfänger oder beides.

+0

Danke für die Antwort. – sawa

+1

Die Tatsache, dass lokale Variablen zum Zeitpunkt der Analyse definiert sind, ist der Grund für das etwas unintuitive Verhalten von 'if false though foo = 43 end; foo # => nil (anstelle von NameError) '. –

+0

@ JörgWMittag Das macht Sinn. –

0

Sie stellen eine große Frage. Wie Sie darauf hinweisen, möchte Ruby es als Konstante behandeln und daher ständig nachschlagen.

Das folgende Snippet zeigt jedoch das aktuelle Verhalten, und durch Ändern von const_missing scheinen Sie das gewünschte Verhalten zu erhalten. Und um dir die Wahrheit zu sagen, kann ich nichts kaputt machen.

Meine Schlussfolgerung ist, dass dies war, wie jemand bereits vorgeschlagen, nur eine Design-Entscheidung, aber es ist seltsam, weil im Allgemeinen Rubin Konvention gegen Durchsetzung bevorzugt.

Oder ich vermisse einen Fall, in dem Dinge verwirrend werden und das Falsche passiert.

<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

Es gibt keinen großen Grund für den Unterschied. Ich wollte nur, dass foo sich wie foo() verhält, wenn es keine lokale Variable foo im Bereich gibt. Ich dachte, es wäre nützlich, um DSL usw. zu erstellen. Aber ich sah keinen Grund, Foo dazu zu bringen, sich wie Foo() zu verhalten.

+4

Was für eine Überraschung!本 物 の 松本 ん ん で か. – sawa

Verwandte Themen