Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does add: return the object added in Smalltalk collections?

Background

Something that catches every Smalltalk newbie is that add: does not return "self" but the object being added.

For example, with this code:

myCollection := OrderedCollection new 
  add: 'Peter';
  add: 'John';
  add: 'Paul'.

myCollectionwill containt the String "Paul", and not the collection itself.

This is because add: returns the object being added, and the whole cascade expression evaluates to the last message being sent.

Instead, it should be written with yourself at the end:

myCollection := OrderedCollection new 
  add: 'Peter';
  add: 'John';
  add: 'Paul';
  yourself.

Questions

  • Why is this so?
  • What was this designed this way?
  • What are the benefits of add: behaving this way?
like image 992
Sebastian N. Avatar asked Dec 27 '12 00:12

Sebastian N.


2 Answers

I've thought about this a lot. I've never heard any of the original designers of Smalltalk defend this decision, so we don't know for sure why they did it. I've decided that the reason was because of cascades. If add: returned the receiver, then (things add: thing1) add: thing2 would be the same as things add: thing1; add: thing2. By having add: return the argument, those two expressions are different and the programmer can use each when it is appropriate.

However, I think it is a mistake. I've been teaching Smalltalk for over 25 years, and every time I teach it, people have trouble with this. I always warn them, but they still make mistakes with add:. So, I consider this a bad design decision.

This design decision is about the library, not the compiler. You could change it by going into the collection classes and changing them. Of course, it is impossible to predict how many Smalltalk programs would break. Collections are so fundamental that this change would be as hard to make as a real change to the language.

like image 170
Ralph Johnson Avatar answered Sep 19 '22 08:09

Ralph Johnson


In other languages you can write:

b[j] = a[i] = e;

This is somehow preserved in Smalltalk if at:put: returns the put object:

collectionB at: j put: (collectionA at: i put: e).

The same interest exist for add: / remove: which allow this kind of chaining:

collectionB add: (collectionA add: anElement).
collectionB add: (collectionA remove: anElement).
like image 37
aka.nice Avatar answered Sep 21 '22 08:09

aka.nice