Why we should remove {} from Squeak

ducasse stephane ducasse at iam.unibe.ch
Wed Oct 3 08:06:42 UTC 2001


on 3/10/01 8:54 am, Richard A. O'Keefe at ok at atlas.otago.ac.nz wrote:

> 1) {}'s encourage poor object-oriented programming style. Our experience
> has shown that many situations where dynamically constructed arrays are
> returned from a method, the programmer really should have defined a new
> class to represent the result. (See
> http://www.smalltalksystems.com/publications/misuse_of_arrays.doc (requires
> MS Word))
> 
> Can someone make a Postscript or PDF version of this and put it somewhere?

This is on Steven pope site and included in the Squeak collectuive book cd.


> In this regard, {}'s are an attractive nuisance, particularly
> for novice programmer who should be learning to define new
> abstractions rather than using arrays.
> 
> This is the old "REAL oopy methods never return more than one result"
> religion again, and I for one don't believe it.  For an extreme version
> of this dogma, see Eiffel, where a method that has a side effect is not
> supposed to return a result, so reading looks like
> source.try_to_read
> if source.read_worked then
> ... source.last_thing_read ...
> Lisp, Scheme, Prolog, Mercury, and Mesa all take the view that there is
> nothing outlandish about returning more than one result.  In ML, Haskell,
> and Clean, I find myself returning a heck of a lot of tuples, which the
> compiler then works hard to eliminate in favour of _really_ returning
> more than one value.
> 
> Here's a favourite example of mine.  In my XML kit, I have a function
> that finds a place in a tree and splits it at that point.  Conceptually,
> it's quite simple:
> 
> split_before :: (Tree -> Bool) Tree -> (Tree, Tree)
> split_after  :: (Tree -> Bool) Tree -> (Tree, Tree)
> 
> If I followed the Eiffel dogma, I'd have to write
> tree1.split_before(condition)
> tree2 := tree2.piece_split_off
> which requires every tree to have a place to hold a piece split off.
> In Smalltalk, I have a choice of
> 
> (a) tree2 := tree1 splitBefore aBlock.
> (b) aPair := tree1 splitBefore aBlock.
> tree1 := aPair first.
> tree2 := aPair second.
> (c) anArray := tree1 splitBefore aBlock.
> tree1 := anArray first.
> tree2 := anArray second.
> 
> each of which has flaws:
> 
> (a) => I have to make an entirely arbitrary decision about which part of
> the tree counts as "the same" tree afterwards and which part counts as
> "the new" tree.  Conceptually, the old tree has disappeared, and two
> new trees exist, the interface forces me to make this choice.
> 
> (b) => The Pair class has NO semantics other than to hold a pair of things.
> (Trees in this case.)  There just isn't anything to add.  (No, there
> isn't any general "here is a pair of trees, glue them together"
> operation in this case.  The bleeding edges have to match up.)
> 
> (c) => There is the possibility of an Array result having too few or too
> many elements.
> 
> This argument against {} is futile, because there is nothing to stop
> someone defining Pair and Triple classes (or any other n-tuple they need)
> and using those.  Indeed, I mailed just such classes to this mailing list
> early last month as part of the support for
> aCollection with: anotherCollection [with: yetAnotherCollection]
> 
> It is not clear to me that replacing
> {left. right}
> with
> Pair first: left second: right
> is much of a gain.
> 
> 2)  The most common reasonable use of {}'s seems to be in grouping a set of
> similar items to be passed as a single method argument. This is really just
> a poor man's way to implement a variable length method argument list. There
> are interesting proposals that have been made for adding variable length
> argument lists to Smalltalk. If one of these were implemented, the more
> general {} construct would not be needed.
> 
> Yes, but no such construct DOES exist in ANSI Smalltalk or Squeak. 
> This is like saying "You don't need a loaf of bread, a cake would be much
> better.  And no, I'm NOT going to give you a cake."  Feh!
> 
> One is also obliged to admit that Smalltalk has a lot of code in the
> system, starting with #perform:withArguments:, that likes to put arguments
> in arrays.
> 
> One should also note that passing arrays allows an argument list to vary
> in several ways, not just one.  In Lisp terms, you can have as many
> &rest arguments as you want.
> 
> There are two other uses in Squeak, the first of which seems to be very
> common, and seems to me entirely reasonable:
> 
> (3) Creating an array that would have been an array literal had array
> literals allowed Points, Colors, Booleans, and so on as elements.
> (To be sure, Points are mutable, but so are strings, and array
> literals allow them.)
> 
> (4) The caseOf: construct.
> 
> {} syntax is comparatively easy to support in a compiler.
> It doesn't need any new methods in the collection classes,
> no new collection-class-related classed, not even any new node
> types, just an additional parsing method or two.
> When you see {e1. ... en} just construct the same nodes that would have
> been constructed had
> ((Array basicNew: n) basicAt: 1 put: (e1); ...
> basicAt: n put: (en); yourself)
> appeared in its place.  (Yes, this is an argument that caseOf: should
> work with this pattern, identically to a curly braced form.)
> 
> This means that once people get used to {} and find idioms where it
> expresses things that are awkward to express otherwise, it's going to
> be hard to stop projects forcibly adding it to their compiler if it
> isn't there, short of putting the compiler behind a brick wall.
> 
> 
> 





More information about the Squeak-dev mailing list