Why is the method call necessary if it can, in principle, be a constant?

Method calls can usually omit the receiver and parentheses for arguments:

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

In the above case, foo ambiguous between a method call and a reference to a potential local variable. In the absence of the latter, it is interpreted as a method call.

However, when a method name can, in principle, be a constant name (i.e. when it starts with a capital letter and consists only of letters), this seems to require a value.

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

Why is this so? Why should a method call be explicitly distinguished from a constant reference even if there is no constant with the same name?

+6
source share
3 answers

The set of local variables, which is in scope at any given point in the program, is defined lexically and, thus, can be determined statically, even when the analysis time. Thus, Ruby even knows, before runtime, which local variables are in scope, and thus can distinguish between the send message and the local difference of variables.

Constants are viewed first lexically, but then through inheritance, i.e. dynamically. It is not known which constants are in the region before execution. Therefore, in order to eliminate ambiguity, Ruby always assumes a constant, if this is clearly not the case, that is, it accepts arguments or has a receiver or both.

+5
source

There is no big reason for the difference. I just wanted foo to behave like foo () if there is no local variable foo in the scope. I thought it was useful for creating DSL, etc. But I saw no reason to make Foo act like Foo ().

+2
source

You ask a big question. Since you indicate that ruby ​​wants to treat it as a constant and therefore do a constant search.

The following snippet shows the current behavior, and then by changing const_missing you seem to get the desired behavior. And honestly, I can’t break anything.

My conclusion is that it was, as someone already suggested, just a design decision, but its strange, because in general the ruby ​​stands for an agreement against enforcement.

Or am I missing some case where things start to get confused and something goes wrong.

 <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> 
0
source

All Articles