This post originated from an RSS feed registered with Ruby Buzz
by Florian Frank.
Original Post: Ruby's rich Array API
Feed Title: The Rubylution
Feed URL: http://rubylution.ping.de/xml/rss/feed.xml
Feed Description: The Rubylution is a weblog (mainly) about Ruby Programming.
There's an ongoing discussion in the Blogsphere about Ruby's Array API, that was started by Martin Fowler.
Elliotte Rusty Harold obviously didn't like it as much as Martin did. His article is full of misunderstandings and it seems, that the only research he did, was skimming and scanning the Ruby Array documentation, trying to find something to dislike. (That would be anything, that's not like it is in Java.) I mean, if he truly had questions about Ruby, why didn't he ask on the Ruby Talk Mailing List? Rubyists are nice people, he would have gotten lots of answers in no time.
He seemed to dislike the Array API, because it offers a lot of useful methods, that one would expect in several different data structures instead of a single one. From the Ruby user's point of view a richer API isn't bad: Blending queues, stacks, sets, arrays and lists in one class, only makes its instances more useful. You don't have to use Array#to_a on an array, that is used as a stack. But it sure pays off to have it available, if you want to output it for example:
puts *stack
(The splat operator * is calling #to_a to do its work.) Or to iterate over its elements
for elm in stack
end
which requires the #each method.
This is a pragmatic approach: You don't have to find a way to convert a stack into an array first.
One problem with this is that inheritance is more difficult, because a class that extends Array would have to support all of the Array instance methods. Inheriting from Array is a newbie error in Ruby - it's much better to delegate to an encapsulated Array instance instead, in order to restrict the supported protocol. There are several ways to do this in Ruby: manually, method_missing, forwardable.rb, delegate.rb, and you can easily define your own delegate meta programming method.
Another problem is that offering a full duck typing protocol compatible to that of Array for your own classes is a lot of work. It would of course be possible to offer a mixin, that only expects a few methods to be in your class, and then offers a default implementation of all of Arrays instance methods based on those. This wouldn't be as efficient in every case, but would make it at least more easy. But these difficulty only occurs, if you really want to write your
own "quacks like an array" type of classes from scratch.
In Ruby it's quite easy to achieve the effect of restricting the protocol an object will understand by means of meta programming. It's possible to extract a class that only offers a subset of the original protocol:
The List objects will still respond to all Object and Enumerable instance methods (second parameter to extract). You can mimic Java's get and put methods as well:
To create a tool set that supports this is quite easy: Just duping the Array class object and reconfigure it's protocol. It can be done in 42 lines of Ruby. Here's the implementation and some additional examples. Is it possible to do that in 42 lines of Java, too?