Over the past few days I have been picking up some Ruby. Overall, I enjoy the fully object oriented nature of the language. An interesting aspect of Ruby is its collections and the ability to create a heterogeneous or mixed set of objects. Although there are a number of debates on the usefulness of these types of collections, it is a good feature for those rare cases. One drawback of this feature is some methods such as .sort will produce an Error when applied to the mixed collection. One way to prevent this would be to detect if a collection was heterogeneous prior to the method call. After digging around, I found there was no clear way to detect this. So for any future padawan learner of Ruby I will share my solution.
# Detect for heterogeneous array
array = [1, 4, "hello", [2, 4], 3.5]
if array.map {|e| e.class}.uniq.size > 1
puts "Heterogeneous Collection"
end
Using the map iterator, the code will generate a new array of object class definitions for every object in the collection. Now, it is a matter of checking for the number of uniques in the resulting array. If it is more than one, you will have yourself a mixed collection.

Randy
Jun 10, 2012 -
This variant is faster because it bails out immediately upon detecting a different class.
array.any? { |el| el.class != (@el ||= el.class) }
Also, a shorter implementation of the first variant is:
array.count(&:class) > 1
Gavin Stark
Jun 11, 2012 -
array.each_cons(2).any? { |a,b| a.class != b.class }
Eliminates the need for an instance variable.
Paul
Jun 11, 2012 -
This will violate the Liskov substitution principle! Would asking the objects in the collection if they respond to the appropriate method yield better results.
Rob Britton
Jun 12, 2012 -
Agreed, in fact this will fail in some actual good use cases, for example:
[5, -2.3, 10**100].map &:class # => [Fixnum, Float, Bignum]One useful case of mixed collections is function arguments. While Ruby doesn’t allow named arguments like Python or some other languages, you can simulate them using a Hash and some of Ruby’s syntactic sugar:
def foo options = {}
# …
end
# In Ruby if the last argument to a function parses as a hash literal, it is passed to the function as a single hash object
ption1 => 5,
ption4 => “hello”,
ption2 => lambda { … }, …
foo
This is extremely useful in some cases because you don’t need to specify all the arguments to a function, nor do you need to remember the order. Many Ruby libraries (and other dynamic languages like Javascript) use this pattern all over the place for functions/methods that take a large number of mostly optional arguments without ever having to manually write out all of the arguments.
John Carney
Jun 11, 2012 -
This strikes me as addressing the wrong problem. Why are you building heterogenous collections then trying to sort them? Either the collections should be homogenous by design, or you shouldn’t be trying to sort them.