We're working on something new! Hook Relay gives you Stripe-quality webhooks in minutes. Sign up for free today!

The clever hack that makes `items.map(&:name)` work

The &: trick is a great shortcut when using enumerable methods like map. The way it works may surprise you. In this post we'll look in detail at exactly how code like `users.map(&:name)` functions under the hood.

When iterating over arrays, there's one piece of shorthand that I find myself using again and again. It's the &: trick, aka the "ampersand colon" or "pretzel colon". In case you're not familiar with it, here's how it works:

words = ["would", "you", "like", "to", "play", "a", "game?"]

# this...
words.map &:length

# ..is equivalent to this:
words.map { |w| w.length }

Until recently, I had assumed that the &: syntax was an operator. But it's not. It's a clever hack that started out in ActiveSupport and became an official feature in Ruby 1.8.7.

The & operator

In addition to being used for AND logic operations, the "&" character has another use in Ruby. When added to the beginning of a method argument, it calls to_proc on its operand and passes it in as a block. That's a mouthful. It's much simpler to see the example:

def my_method(&block)

class Greeter
  def self.to_proc
    Proc.new { "hello" }

my_method(&Greeter) # returns "hello"


You can add a to_proc method to any object, including Symbol. That's exactly what ruby does to allow for the &: shortcut. It looks something like this:

class Symbol
  def to_proc
    Proc.new do |item|
      item.send self

Clear as mud? The important part is item.send(self). Self, in this case refers to the symbol.

Putting it all together

Enumberable methods like each and map accept a block. For each item they call the block and pass it a reference to the item. The block in this case is generated by calling to_proc on the symbol.

# &:name evaluates to a Proc, which does item.send(:name)

The interesting thing about this is that map  doesn't  know any of this is going on!  The bulk of the work is being done by the :name symbol. It's definitely clever...almost too clever for my taste. But it's been a part of Ruby's standard library for years at this point, and it's so handy I doubt I'll stop using it for now. :)

Honeybadger has your back when it counts.

We're the only error tracker that combines exception monitoring, uptime monitoring, and cron monitoring into a single, simple to use platform. Our mission: to tame production and make you a better, more productive developer.

Learn more
author photo

Starr Horne

Starr Horne is a Rubyist and Chief JavaScripter at Honeybadger.io. When she's not neck-deep in other people's bugs, she enjoys making furniture with traditional hand-tools, reading history and brewing beer in her garage in Seattle.

More articles by Starr Horne
“We've looked at a lot of error management systems. Honeybadger is head and shoulders above the rest and somehow gets better with every new release.” 
Michael Smith
Try Error Monitoring Free for 15 Days