Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Ruby, if we define a method call "c=", why can't it be invoked by c = 3?

Tags:

ruby

For example, if we

def c=(foo)
  p "hello"
end

c = 3
c=(3)

and no "hello" will be printed. I know it can be invoked by self.c = 3 but why? and in what other ways can it be invoked?

like image 809
nonopolarity Avatar asked Feb 24 '11 22:02

nonopolarity


People also ask

What happens when you call a method in Ruby?

In ruby, the concept of object orientation takes its roots from Smalltalk. Basically, when you call a method, you are sending that object a message. So, it makes sense that when you want to dynamically call a method on an object, the method you call is send . This method has existed in ruby since at least 1.8.

Can you define a method within a method in Ruby?

There's no reason to define a method using def from within a method. You could always move the same inner def construct out of the outer def and end up with the same method. Additionally, defining methods dynamically has a cost. Ruby caches the memory locations of methods, which improves performance.


1 Answers

c = 3 (and c = (3), which is completely equivalent to it) is always interpreted as a local variable assignment. You might say it should be interpreted as a local variable assignment only if a method c= is not defined on self, but there are various problems with that:

  1. At least MRI needs to know at parse time which local variables are defined in a given scope. However it is not known at parse time, whether a given method is defined or not. So ruby couldn't know whether c = 3 defines the variable c or calls the method c= until runtime, which means it wouldn't know whether a local variable c is defined at parse time. This means that MRI would need to change the way it handles local variables in the parser, to make it work like you want it to.

  2. It wouldn't be possible to define a local variable named c if a method is c= is already defined. You might say that's okay, because having local variables and methods with the same name is confusing anyway. However consider the case, where you define method_missing so that foo= is defined for every possible foo (as is the case on OpenStructs for example). In that case it would not be possible to define local variables at all.

  3. You can't tell for sure, whether an object responds to c= without running it because it might be handled by method_missing. So the whole thing would actually be undecidable.

like image 195
sepp2k Avatar answered Oct 15 '22 23:10

sepp2k