Why do variable prefixes in ruby ​​allow parentheses to be excluded in method calls?

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

+6
source share
2 answers

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

Suppose instance variables do not have the @ 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 above case, the instance variable foo initialized using a 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 bar method, if the brackets are not involved in the method call, how can the interpreter indicate whether self.foo method call or access to an instance variable?

Maybe we can allow shadow instances of instance variables in the absence of brackets, but this leads to inconsistent syntax of the language itself. For example, because of the scope of the definition of MyClass :

 obj = MyClass.new # Call instance method obj.foo 

This is an instance method call because all instance variables are invisible from the outside (at least without the use of metaprograms). But self.foo (without parentheses) in the bar method is access to the instance variable. This syntax inconsistency can lead to errors. In addition, this makes it difficult to implement the interpreter itself.

. What about allowing instance methods to shadow instance variables? Programmers then need to make sure that the instance variable names do not interfere with the instance instance names, otherwise the instance variables become unavailable. It is very difficult if a class has a long chain of ancestors, because collisions need to be checked not only in the current definition of the class, but also for its ancestors, and this violates encapsulation.

In any case, the price is much higher than adding a prefix to instance variables. For classes and global variables, the situations are similar.

+1
source

Let's look at an example:

 def foo 10 end p foo #=> 10 foo = 'hi' p foo #=> hi p foo() #=> 10 

If we define a local variable whose name matches the name of the method in the same scope, then we lose the binding to the method name, since the variable name takes precedence. You can use parentheses to resolve the ambiguity.

The book seems to describe this phenomenon in detail, and makes a constructive decision to provide flexibility when you need to use characters like @ to define instance variables so that the corresponding access methods ( var and var= ) can be called without parentheses, and it seems that one accesses the variable, although in reality you are calling the method.

... you will see the punctuation marks at the beginning of the Ruby names variable: global variables have the $ prefix, instance variables with the @ prefix and class variables with the @@ prefix. These prefixes can get a little used, but after a while you may come to understand the fact that the prefix tells you about the scope of the variable. Prefixes are needed to disambiguate Rubys with a very flexible grammar. One way to think of variable prefixes is that they are the one price we pay for omitting parentheses around method calls.

0
source

All Articles