Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do variable prefixes in ruby allow omission of parenthesis in method invocations?

Tags:

semantics

ruby

In The Ruby Programming Language by David Flanagan; Yukihiro Matsumoto, they state that the variable prefixes ($, @, @@) are one price we pay for being able to omit parentheses around method invocations. Can someone explain this to me?

like image 426
MykelXIII Avatar asked May 16 '16 00:05

MykelXIII


1 Answers

Here is my immature opinion. If I'm wrong, please correct me.

Suppose the instance variables don't have a @ prefix, then how do we declare an instance variable?

class MyClass
  def initialize
    # Here foo is an instance variable
    self.foo = 'bar'
  end

  # Here foo is an instance method
  def foo
  end

  def bar
    # Call method. No doubt.
    self.foo()

    # Call method? Access instance variable?
    self.foo
  end
end

In the case above, the instance variable foo is initialized using the hypothetical syntax

self.foo = 'bar'

because we must have a way to tell the ruby interpreter that foo belongs to the current instance and is not a local variable.

Then in the method bar, if parentheses are not enforced in method invocation, how can the interpreter tell whether self.foo is a method invocation or an instance variable access?

Maybe we can let instance variables shadow instance methods when parentheses are missing, but this causes syntax inconsistency of the language itself. For example, from outside the MyClass definition:

obj = MyClass.new

# Call instance method
obj.foo

It's an instance method invocation because all instance variables are invisible from outside (at least without using meta programming). But the self.foo (without parentheses) in the method bar is an instance variable access. This syntax inconsistency may lead to bugs. Also, it brings difficulty in implementing the interpreter itself.

Then what about letting instance methods shadow instance variables? Then the programmers have to ensure the instance variable names don't collide with instance method names, otherwise the instance variables become inaccessible. It's very difficult if a class have a long ancestors chain because one must check collisions not only in the current class definition, but also in its ancestors, and this breaks encapsulation.

Either way, the price is much higher than adding a prefix to instance variables. For class and global variables, the situations are similar.

like image 123
Aetherus Avatar answered Sep 26 '22 00:09

Aetherus