Zee Spencer

The Ruby & Symbol

& is a powerful ruby operator, when you use it as a unary operator it has two main use cases:

The most common is to pass an object as a block to a method, like this:

[1,2,nil, 3].reject(&:nil?)

This calls #to_proc on the symbol :nil?, converts the result into a block, and passes it to the reject method. A line by line breakdown looks something like this:

[1,2,nil, 3].reject(&:nil?)
[1,2,nil,3].reject(&(proc = :nil?.to_proc))
[1,2,nil,3].reject(&proc)
[1,2,nil,3].reject { |e| e.nil? }

The second is explicitly declaring a block by using the & in a method definition:

def print_results(&block)
  p block.yield
end

print_results { "bar" }

With an explicitly named block you can do useful things, like map a block to all the columns in a table:

def column_map(table, &block)
  table.map { |row| row.map(&block) }
end

column_map([[1,2,3],[4,5,6],[7,8,9]]) { |v| v + 5 }

And of course, explicitly named blocks still allow you to expand an object to a block:

column_map([[1,2,3],[4,5,6],[7,8,9]], &:odd?)

For more reading on the & operator, check out The Ampersand Operator in Ruby by Pan Thomakos.

I you want to grok blocks, I'd recommend the excellent Understanding Ruby Blocks, Procs and Lambdas by Robert Sosinki


Browse posts about:

Want to get notified when I publish new articles or update old ones? Subscribe to my newsletter. It's a weekly-ish set of interesting links with a short essay on programming, design, technical leadership, or anything else that strikes my fancy.

Not sure? Read the archive.