Search code examples
rubymessagingselfmessage-passing

What is an appropriate way to think of the 'self' keyword in Ruby?


Regarding the semantics of self, is it more appropriate to say:

  1. self is a keyword that holds a reference to whatever the current receiver is.
  2. self is the only receiver in Ruby. When you call a method or invoke a class definition, the value bound to self becomes a copy of the value bound to that object. By value, I mean unsigned long VALUE

In other words, is it ever accurate to say that myObj is the actual receiver of a message, or is it instead the case that self is the true receiver and a copy of the unsigned long VALUE variable value that is bound to the myObj variable name gets bound to the self variable name?

In the latter case, you could only ever say that self is receiving a message, but self and myObj happen to reference the same object. (self is always the current object)

In the former case, you could actually say that the current object (message receiver) changes and Ruby just updates self accordingly.

Whats going on under the hood?

The reason I am concerned with this apparently arbitrary distinction is because I am trying to figure out how Ruby "passes a message"


Solution

  • When you "pass a message" to an object, the message name is used to determine which method definition to execute. As arguments, that method definition receives both the rest of the message and the value to be used for self.

    So from the point of view of the method code, self is just another parameter. But in the Ruby source, instead of being declared in the method's formal parameter list, it's implicit.

    In that sense, it's certainly not true that only self can receive messages, because the invocant of a message only becomes self after the message is received, and continues to be so only within the body of the method responding to that message.

    Javascript, like Ruby, has a predefined name (this instead of self), but other languages deal with the invocant differently. Some let you pick your own name for it, which may differ between method definitions. Maybe the invocant is just the first formal parameter, as in Perl and Python; the answer to your question may be clearer in those languages. Or, since the syntax to specify the recipient of a message is normally different from the syntax of a passed-in argument, there might likewise be a special syntax for declaring an invocant parameter, as in Go.

    Ruby has the additional wrinkle that a bareword which doesn't refer to a local variable is interpreted as a message with no explicit invocant, and automatically sent to self. Other than that, self is just another local variable (which happens to be predefined and read-only).