Why do methods return the default self in Smalltalk?

Background

In Smalltalk, if you do not explicitly return anything, the message is evaluated to the recipient (or β€œme” in the context of the message).

For example, given this method:

MyClass >> myMethod Transcript show: 'hello'; cr. 

Rating (doint "print-it") this:

 | myInstance | myInstance := MyClass new. myInstance myMethod. 

If <print-it> is executed before the last call, then the result will be the instance itself.

Questions

  • Why was it designed this way?
  • What is the idea of ​​this?
  • What was the philosophical background?
  • What are the practical benefits of this? Is this a relief to the chain of methods?
+8
oop smalltalk squeak pharo visualworks
source share
5 answers

One very simple reason has not yet been indicated: in a virtual machine, returning self is simpler and more efficient than returning any other object.

Small byte codes implement a stop machine. This means that arguments are passed by pushing them onto the stack, rather than pushing them into registers. In addition to the arguments specified in the method signature, a hidden argument is always passed, which is the recipient of the message. Therefore, even for unary methods (without arguments), the receiver is pushed onto the stack, then the method is executed, and the receiver value on the stack is the way the method knows "I". Returning "self" if no explicit return statement is specified, the VM can simply leave "self" oop on the stack, which saves at least one memory storage operation. Thus, in terms of efficiency and simplicity, the return of the self is the most elegant thing.

+10
source share

The Smalltalk-80 Blue Book (language and its implementation) says nothing about why it returns the default recipient.

However, there is a quote on page 27 (section "Return Values") that may help you:

"Even if no information should be sent back to the sender, the recipient always returns a value for expressing the message. A return value indicates that the response to the message is complete. (...)"

Keep in mind that Smalltalk methods are activated by sending messages, so there is full feedback for the message (which may end with the exception MessageNotUnderstood). The concept of sending messages is of utmost importance.

There are several examples of good practice regarding what needs to be returned depending on the intention of the message, but this is the subject of a different story.

+6
source share

I'm not the creator of a little trick, but it seems like this is the best you can do.

For example, if you do:

 var := myInstance myMethod. 

then the question arises: what do you want var to become? One option would be nil . But this is a bit confusing because you are working with certain objects, and nil is actually undefined. That way, you can relate to it when you assign myInstance var and just call myMethod along the way. Also, this can probably be considered a reduction for

  var := myInstance myMethod; yourself. 

If you look from the inside, then of all the data available to the object itself, the most suitable thing is probably also self . Once again, nil can be returned, but I already said my opinion about this before.

In Smalltalk there is no such thing as a void method that returns nothing, and type checking does not exist. Therefore, the method just needs to return something. He, like the object, says:

I can return myself for any call to the default method, because I always find out about myself, and you can override this behavior if you want to return something else to me.

Personally, I think that returning nil can also be good, and Objective-C applications use nil things very often, but Smalltalk is created this way, and I think this is a good solution.

+5
source share

Methods return self by default for several reasons.

  • Smalltalk methods must return something
  • self is the easiest object to return
  • self is the fastest object to return
  • The return of self allows multiple design patterns to work naturally.

Let me explain # 4 a little more. One common pattern for initializing an object is to define a new method for a class that looks like this:

 new ^super new initialize 

This pattern depends on the initialization of the returning itself. However, it is not entirely normal to add ^ self at the end of the method to initialize . This is optional because the method will return itself anyway.

In the end, returning yourself is a natural default choice, given that you must return something.

+3
source share

Starting with Java, you know about NullPointExceptions when dealing with undefined return values. In addition, your code should do a conditional check on the null value here and there.

Therefore, I was happy to find a return value for each method call or send message in Smalltalk. If you decide that each method will return a value, you are going to ask what your default value is. The object itself (self) is a very natural way of using it as the default value. Or ask the other way around: what could be the best return value?

0
source share

All Articles