This post originated from an RSS feed registered with Ruby Buzz
by Trans Onoma.
Original Post: Conceiving an Indexable Mixin
Feed Title: TRANSONOMA
Feed URL: http://feeds.feedburner.com/transonoma
Feed Description: A Light Green Agile Programming and SciTech Blog
Today, I have been thinking about the concept of an Indexable mixin, wondering if there is enough formal commonality between Hash and Array to achieve such a clean separation of functionality. The central thesis, if you will, is that an Array's index is akin to a Hash's key. Some interesting observations arise.
My first consideration was on which methods the mixin would depend. The method #at seemed the best candidate (although later #fetch seemed more appropriate). I immediately started trying to add methods that depended solely on this. The method #values_at was easy enough. But I quickly found my options limited. What was wrong? Well, the first thing I noticed was that I was unable to create a #has_index? method. Why? One possible reason is that Ruby returns nil if #at is out of range. Either an error needs to be raised, which can be caught, or it must return something like nack. But the next thing I noticed was the inability to write an #indicies method to return a list of all the viable "at references", namely the Array's indexes and the Hash's keys. Was #indicies actually a fundamental method then? Beyond that a #store method seemed a good way to open things up, allowing content of the Indexable to be changed; and if that same method could be used to remove items too, so much the better. Then again, I imagine, not all Indexable things are necessarily writable, but then #store wouldn't respond, so I suppose it's okay.
Upon deeper consideration it seems more logical that there would be three mixins: Indexable, Enumerable and Iterable. Iterable would actually be what Enumberable is now. Enumerable would then represent something similar to Indexable, but restricted to an ordered integer index, or enumerator. Given these, a Hash is Indexable and Iterable, but not Enumerable. And an Array is Iterable and Enumerable. An OrderHash, interestingly enough, is all three. Actually an Array is also all three if we equate the index and the enumerator, which is quite doable since the enumerator is a strict subset of the index --we'd essentially just end up with a number of aliases.
In exploring this, the most interesting notion that came to me, was how would a write a method that depended on the fact that something partook of more than one mixin, both Iterable and Enumerable for example? After all you can't just write:
module Enumerable & Iterable def ...
It would certainly be interesting if you could. In fact I speculate something like this has a lot to do with Subjective Oriented programming. Without an ability to do this kind of dual-orientation, the tendency would of course be to put that relevant methods in all the classes inheriting Enumerable and Indexable --very anti-DRY. Realized or not, I think it likely this is largely responsible for why Ruby has only Enumerable for all three concepts.
Concept, concepts, concepts. That really is a source of much difficulty. I mean, how do we convey a concept to a computer? All we programmers do is again and again teach it procedures by route. Thus our preverted addiction to syntax and design patterns, as we desperately try to tease conceptuality out of structure.