Why does a method call need to be disambiguated when it can in principle be a constant?

后端 未结 3 607
野性不改
野性不改 2021-01-03 00:20

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

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

In the case abov

相关标签:
3条回答
  • 2021-01-03 00:40

    You ask a great question. As you point out ruby wants to treat it as a constant and therefore do a constant lookup.

    The following snippet however shows the current behavior, and then by modifying const_missing, you seem to get the desired behavior. And to tell you the truth I can't seem to break anything.

    My conclusion is that this was as somebody already suggested, just a design decision, but its odd because in general ruby favors convention vs enforcement.

    Or I am missing some case where things do get confusing and the wrong thing happens.

    <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 讨论(0)
  • 2021-01-03 00:41

    The set of local variables which is in scope at any given point in the program is defined lexically and can thus be determined statically, even as early as parse time. So, Ruby knows even before runtime which local variables are in scope and can thus distinguish between a message send and a local variable dereference.

    Constants are looked up first lexically, but then via inheritance, i.e. dynamically. It is not known which constants are in scope before runtime. Therefore, to disambiguate, Ruby always assumes it's a constant, unless obviously it isn't, i.e. it takes arguments or has a receiver or both.

    0 讨论(0)
  • 2021-01-03 00:42

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

    0 讨论(0)
提交回复
热议问题