I imagine this has come up before, though I can’t find anything about
it. I
was talking to a friend last night who mentioned that in Smalltalk, the
#collect and #select methods (and some others) return the same type as
the
object they’re called on, and in Ruby they always return an Array, no
matter
what the receiver type is. This seems like a good idea to me, though
there
are some questions:
-
What do they mean when applied to a Hash? Do you want a list of
values,
or keys, or pairs? Or do you want to map each key and value to a
different
key and value, and have #map build a Hash for you? If so, how do you
represent that as a return value? Is it [key, value] or {key => value} ? -
Is part of the contract of #map that you get back a collection of the
same size as the input? If so, what happens if you #map a Set and
produce
duplicates? The output will be smaller than the input (similarly for
hash
key collisions). Certainly from an FP viewpoint, a map is a one-to-one
transform from input to output values, so it would seem logical to have
as
many output values as input values. -
There is no uniform method for adding items to a collection. We have
Array#<<, Hash#[]=, Set#add and Set#add?. For linked lists, adding to
the
collection would involve changing pointers on existing members of the
collection. Is it possible to come up with a single method/message whose
role is to provide a uniform way to add something to any collection?
These are pretty much of the top of my head, but I’d be very interested
in
hearing discussion of pros and cons, and any history that shows why Ruby
differs from Smalltalk. I also heard that Ruby 2.0 will “correct” this
behaviour – is this true? Any discussion and/or links to further
reading
welcome.
P.S. This was raised through a discussion of JS.Class[1], which
implements
Enumerable, Hash and Set. The Enumerable methods return native
JavaScript
arrays, which don’t have the Enumerable methods – this causes some
frustration and breaks the Ruby-like model the library is designed to
support.