Warning: this contains code fragments with the pre tag, which look OK in a web browser but not in BottomFeeder
A general bit of Smalltalk stuff, prompted by a discussion from comp.lang.smalltalk. Usually I avoid threads with 50 messages a day, but I sampled one randomly and it reminded of a favourite topic. Credit to Anthony Lander for this insight. For the original, and some interesting material on doing 3-d graphics and video games with Smalltalk, see this link (PDF) . This part is right at the end, page 56-58.
Multiple returns is a language feature that lets a method return more than one value. It allows you to avoid having a method return a collection when all you really want is to return two values and get them into variables. Python is probably the most popular current language with this feature.
So, in Smalltalk, suppose that we had two collections and we want to know the elements in one but not the other, delete the old ones that are gone, and insert the new ones. We could do this as
beforeButNotAfter:= self findElementsOf: before notIn: after. afterButNotBefore := self findElementsOf: after notIn: before. beforeButNotAfter do: [:each | each delete]. afterButNotBefore do: [:each | each insert].
But apart from being verbose that's probably not too efficient. It'd be nice if we could do it in one statement.
beforeButNotAfter, afterButNotBefore := self findNonOverlappingElementsOf: before and: after. beforeButNotAfter do: [:each | each delete]. afterButNotBefore do: [:each | each insert].
Where the comma on the left of an assignment indicated that the method returned two values, and the first one went into the first variable, the second into the second variable. But in Smalltalk about the best we can do is to make a temporary collection
result := self findNonOverlappingElementsOf: before and: after. beforeButNotAfter := result first. afterButNotBefore := result last. beforeButNotAfter do: [:each | each delete]. afterButNotBefore do: [:each | each insert].
Which isn't nearly as nice. The insight, however, is that blocks give us a lot of the same kind of power. Consider
self findNonOverlappingElementsOf: before and: after doing: [:beforeButNotAfter :afterButNotBefore | beforeButNotAfter do: [:each | each delete]. afterButNotBefore do: [:each | each insert]].
Here, instead of multiple return into temporaries, we have a block that defines block temporaries. Our values get into variables with nice names. In the original example that Anthony showed there was an additional wrinkle. This was in the context of 3-d graphics, computing intersections of collections of planes. But they might not intersect. By using the block we can encapsulate the test that's required for that condition, which we otherwise have to put into our code as e.g. a nil test.
For me, this was a real eye-opener. I've used blocks an awful lot, for an awfully long time, even using this kind of a pattern, but it had never occurred to me as being an alternative to multiple return.