This post originated from an RSS feed registered with Agile Buzz
by James Robertson.
Original Post: A Negative Take on Collections
Feed Title: Travis Griggs - Blog
Feed URL: http://www.cincomsmalltalk.com/rssBlog/travis-rss.xml
Feed Description: This TAG Line is Extra
Again! Inspired by David Buck's latest post. He has a great overview of some of the cool things in Python. The one I thought was cute is the ability to index elements from the end of the collection by using a negative index. I thought it would be fun to hack something together that did this for Smalltalk. It's published in the Open Repository as IndexingFromTheEnd.
It's far from a complete work. It does make it so that you can use at: -1 on a good deal of the basic collections in Smalltalk (I tested Arrays, Strings, Symbols, ByteArrays, Intervals, SortedCollections, Lists, and OrderedCollections). There are some collections this does not work on: LinkedLists and collections that combine elements in byte order ways (e.g. DWordArray). These too could be made to work, but I was just playing with proof of concept. There's more than just at: though. Most languages intern this into their syntax, we do not. We have an infinite amount of "indexing" APIs that we can add to collections. So theoretically, one would have to modify some of them to work with "from the end" semantics. For example, at:put: should be modified as well. Many of the others (e.g. at:ifAbsent:) would probably just work correctly because of encapsulation. (aside: In reality, I consider this far scarier than any of the messageNotUnderstood: hacks I've ever put forth)
An interesting note is an analog to David's observations about it "being all about the language" or "all about the IDE." Adding this ability is not really "all about the IDE." But it's not really "all about the language" either. It's more "all about the objects." We didn't need to change the language, mux'ing multiple behaviors into one syntactical element to make this feature work, we extended the behavior of the objects by changing them.
A more Smalltalk oriented approach might be to actually add a new method family, something like back: and back:put:. These would take positive arguments. You could even implement them on Object, and do the computation right there, deerring once computed to whatever the reciever's at:put: implementation.
A bit more cumbersome solution that requires no more code whatsoever is to just use something like:
'Hello World' reverse at: 1
David has an interesting post about what reverse means to Smalltalkers versus the rest of the world. This is fine and quick for small collections. It also has the advantage that all of the existing index based APIs will now work essentially "from the back end".
Or, we could do what we Smalltalkers love so much to do, reify the concept. The concept being that of "arbitrarily remapping the way a sequence is indexed". A wrapper/delegating pattern whereby we create an object that acts as indexing agent into the original. Such a thing already exists actually in the NumericCollections package in the OpenRepository. It's called ReindexedCollection. You create them by sending things like from:by: to a collection. There's even a handy 'backwards' message which is a short cut for 'from: self size to: 1 by: -1'. This is similiar to the reverse thing above, but it doesn't actually make a new collection, so it works great for big collections. The ReindexedCollection is more general too. You can use it to access every other element by using the by: argument. This is real handy for enumerating things like database collections, where every Nth element is what you want. Or for enumerating the blue plane of an image. Or the pink plane.