Enumerable#every
Wednesday, March 25th, 2009By now rubists know the Symbol#to_proc idiom pretty well
[1.4, 2.4, 3.4].map {|n| n.floor } #=> [1, 2, 3]
[1.4, 2.4, 3.4].map(&:floor) #=> [1, 2, 3]
It has become so popular, in fact, that it’s been included in ruby 1.8.7
Funny thing is, the block form is only an extra 3 characters (6 if you want to count spaces). Though I guess the additional “effort” needed to stop and think about what to name the variable is somewhat distracting, especially since the variable is redundant anyway. Regardless, it’s enough of an improvement on such a commonly used idiom that we happily adopted it.
But after having used it plenty (some rails ./script/console hacking sessions can make quite intense use of it), its syntax started feeling heavy.
My favorite way to access an object’s internals is by far the good ol’ dot. I sometimes use OpenStruct instead of a hash just so I can access the values as methods, and I use `andand.method` instead of `try(:method)` for the same reason.
I knew I would be happier if I could use the same trick with #map, so I wrote an Enumerable method. Compare,
enum = [1.4, 2.4 ,3.4]
enum.map {|n| n.floor } #=> [1, 2, 3]
enum.map(&:floor) #=> [1, 2, 3]
enum.every.floor #=> [1, 2, 3]
It has the added advantage that it can take arguments and blocks, so it’s not restricted to only a few methods.
%w( axb dxf ).every.gsub(/x/,'y')
%w( axb dxf ).every.gsub(/x/) { 'y' }
I turned it into a gem so I could easily use it in irb and the rails console, or add it to my rails projects.
To use it:
# on the command line gem sources --add http://gems.github.com gem install mynyml-every # in your app require 'rubygems' require 'every'
If you want to use #every as part of a gem or plugin but don’t want to add a dependency for only a few uses, you can simply make it a git submodule, or even just copy the content into your app since it’s contained in a single file.
Project page: http://github.com/mynyml/every