Shorten Map and Each Commands

Or: Pithy Procs for Working with Enumerables

Typing out code blocks every time you want to use map or each is a bit of a pain, and often unnecessary.

You may know that (1..5).map { |n| n.to_s }  can be rewritten as  (1..5).map &:to_s.

But what does the latter really mean?

The ampersand lets Ruby know you’re passing something to be used as a block and not an argument. It also calls #to_proc on the something. Symbol#to_proc is implemented in C, but for our purposes, it maps to something roughly like this:

Here’s another example:

(1..5).each { |n| puts(n) }  can be rewritten as (1..5).each &method(:puts).

Method#to_proc is also written in C, but the documentation includes a ruby equivalent:

What about something like (1..5).map { |n| n * 2 } ? (1..5).map &2.method(:*).

What else can we pass in? Anything with to_proc. Lambdas? Check.


Implementing #to_proc

Why not add a to_proc method to a command class?

In the above, only one PurchaseCommand is initialized; the same command is used for all items in the cart. It might be a bit clearer to write it this way:

This also allows us to hold a reference to the command for later use, if, for example we wanted do something with its shipment.

Not just for map and each!

This isn’t limited to each and map.

(1..10).partition &:odd?

Be careful, though. While arr.reject &:nil?  is shorter than arr.reject { |i| i.nil? } , arr.compact  is shorter still, and arguably more intention-revealing. At least if you know your enumerable methods.

About Alexander

Alexander has been programming for a very long time. When he met Ruby, it was love at first sight.
This entry was posted in Uncategorized and tagged , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *