Exploring Enumerable in Ruby
One of talks I was able to attend at last week’s RubyFuza conference was by Andrew Timberlake titled ‘Ruby’s Hidden Gems’. It basically revolved around examples of how we often implement something in Ruby that is already supported in the API. I’ve blogged about this before – how I found myself writing C# code, but doing it in Ruby.
A few of the example revolved around the Enumerable module, so I’m going to take a look at some of the built-in methods within this module. We also discussed how it’s good practice to try and implement these methods yourself, so I’m going to try that.
Enumerable#any?
Let’s say you have an array of numbers and you want to test if any of them are higher than 10. You might write the following:
Which is rather ugly and unnecessary. You could also try several of the other Enumerable methods to get to the same result:
Which seems better, until you realize that you should be using the Enumerable#any? method:
Implementing the any? method is pretty straightforward.
Enumerable#all?
As the name implies, this method applies a block to the collection and returns true if the block evaluates to true for all values.
What might the Enumerable#all? method look like if we tried to implement it?
Pretty neat.
Enumerable#take_while
I can’t really imagine a scenario where this method would be useful, but I guess it’s good to know that it exists.
What might the Enumerable#take_while method look like if we had to implement it ourselves?
I feel there should be a nicer way of implementing this, but I can’t really see it.
Enumerable#zip
Once in a while you might find yourself in a situation where you’re working with multiple arrays of the same length containing corresponding values. For example, you might have two arrays – one with a list of names and one with a list of surnames. This usually leads to some pretty messy code when we try to iterate over this.
It’s not all that often that we need to use a for loop in Ruby – we can get rid of it by using the Enumerable#each_with_index method.
This is still pretty messy – luckily Ruby has the Enumerable#zip method. This converts each element to an array and then merges each array with corresponding elements from the arguments. (You can actually pass in multiple argument arrays, which makes it a bit trickier)
Ruby will substitute nil if there are no corresponding elements in the arguments. Can we try and implement Enumerable#zip ourselves?
I’m not too crazy about the double loop – if you have a better implementation, I would love to see it! Happy coding.