I found this code in a RailsCast:

def tag_names
  @tag_names || tags.map(&:name).join(' ')
end

What does the (&:name) in map(&:name) mean?

104 upvote
  flag
I have heard this called “pretzel colon”, by the way. – Josh Lee
4 upvote
  flag
Haha. I know that as an Ampersand. I have never heard it called a "pretzel" but that makes sense. – DragonFax
1 upvote
  flag
Also you can drop out the brackets tags.map &:name for the extra shortest entry. – itsnikolay
62 upvote
  flag
Calling it "pretzel colon" is misleading, although catchy. There is no "&:" in ruby. The ampersand (&) is a "unary ampersand operator" with a pushed together :symbol. If anything, it's a "pretzel symbol". Just saying. – fontno
2 upvote
  flag
tags.map(&:name) is sort from of tags.map{|s| s.name} – kaushal sharma

13 Answers 11

It's shorthand for tags.map { |tag| tag.name }.join(' ')

upvote
  flag
Nope, it's in Ruby 1.8.7 and above. – Chuck
upvote
  flag
Is it a simple idiom for map or Ruby always interpret the '&' in a particular way? – collimarco
upvote
  flag
@Chuck thanks, reverted for correctness. – Oliver N.
7 upvote
  flag
@collimarco: As jleedev says in his answer, the unary & operator calls to_proc on its operand. So it's not specific to the map method, and in fact works on any method that takes a block and passes one or more arguments to the block. – Chuck

It's equivalent to

def tag_names
  @tag_names || tags.map { |tag| tag.name }.join(' ')
end
up vote 443 down vote accepted

It's shorthand for tags.map(&:name.to_proc).join(' ')

If foo is an object with a to_proc method, then you can pass it to a method as &foo, which will call foo.to_proc and use that as the method's block.

The Symbol#to_proc method was originally added by ActiveSupport but has been integrated into Ruby 1.8.7. This is its implementation:

class Symbol
  def to_proc
    Proc.new do |obj, *args|
      obj.send self, *args
    end
  end
end
34 upvote
  flag
This is a better answer than mine. – Oliver N.
79 upvote
  flag
tags.map(:name.to_proc) is itself a shorthand for tags.map { |tag| tag.name } – Simone Carletti
4 upvote
  flag
this isn't valid ruby code, you still need the &, i.e tags.map(&:name.to_proc).join(' ') – horseyguy
upvote
  flag
@banister Thanks, fixed. – Josh Lee
5 upvote
  flag
Symbol#to_proc is implemented in C, not in Ruby, but that's what it'd look like in Ruby. – Andrew Grimm
upvote
  flag
@banister I think you can write tags.map(&:name).join(' ') without the to_proc – Gerry
1 upvote
  flag
"A block may be associated with a method call using either a literal block .. or a parameter containing a reference to a Proc or Method object prefixed with an ampersand character." bit.ly/n8GpYw – Jared Beck
5 upvote
  flag
@AndrewGrimm it was first added in Ruby on Rails, using that code. It was then added as a native ruby feature in version 1.8.7. – Cameron Martin
2 upvote
  flag
Great answer! I think a link to show the entire Symbol implementation class would be useful. github.com/rubinius/rubinius/blob/master/kernel/common/… – Mogox
3 upvote
  flag
@SimoneCarletti - While tags.map { |tag| tag.name } is effectively what tags.map(&:name.to_proc) does, it is not exactly shorthand, per se. This is because procs can be converted to blocks, using the & operator, when they are passed to methods that use yield and thus require a block. (See the Ruby documentation here). As Josh Lee showed in his post above, symbols can also be converted to procs and, from there, can then be converted to a block, which is necessary because map uses blocks. – jazzyfresh
1 upvote
  flag
I found a great article to explain more detailed ampersand operator in Ruby, hope it helps people. The "foo" followed "&" can be either a symbol or an Object. ablogaboutcode.com/2012/01/04/the-ampersand-operator-in-ruby – Jinzhao Huo
2 upvote
  flag
@JaredBeck had it right: the ampersand just tells ruby that "this argument is the block, try your best to make it one if it ain't yet" – Tero Tilus
1 upvote
  flag
You should use #__send__ instead of #send at it's safer. An object can override send for some reason (eg. sending emails), but if you do the same with #__send__, Ruby VM throws a warning. – Luca Guidi
upvote
  flag
it doesn't talk about how symbols are mapped/connected to actual methods. Symbol to proc sounds all good. But symbols are empty how do they become block of code. – Muhammad Umer
1 upvote
  flag
It's not just a shorthand, but also 20% faster and more idiomatic ruby code. – leandrotk
upvote
  flag
If foo is an object with a to_proc method, then you can pass it to a method as &foo. Please illustrate with an example, it's way too abstract for me. What is &foo language construct even called? Don't know what to google to make this more clear. – Marko Avlijaš

Another cool shorthand, unknown to many, is

array.each(&method(:foo))

which is a shorthand for

array.each { |element| foo(element) }

By calling method(:foo) we took a Method object from self that represents its foo method, and used the & to signify that it has a to_proc method that converts it into a Proc.

This is very useful when you want to do things point-free style. An example is to check if there is any string in an array that is equal to the string "foo". There is the conventional way:

["bar", "baz", "foo"].any? { |str| str == "foo" }

And there is the point-free way:

["bar", "baz", "foo"].any?(&"foo".method(:==))

The preferred way should be the most readable one.

21 upvote
  flag
array.each{|e| foo(e)} is shorter still :-) +1 anyways – Jared Beck
6 upvote
  flag
@JaredBeck Yeap! Shorter but not point-free :) – Gerry
upvote
  flag
And it is surprisingly fast. – Boris Stitnicky
upvote
  flag
Could you map a constructor of another class using &method ? – finishingmove
3 upvote
  flag
@finishingmove yeah I guess. Try this [1,2,3].map(&Array.method(:new)) – Gerry
upvote
  flag
Awesome, thanks @Gerry :) – finishingmove
upvote
  flag
exactly what I was looking for! – bodecker

While let us also note that ampersand #to_proc magic can work with any class, not just Symbol. Many Rubyists choose to define #to_proc on Array class:

class Array
  def to_proc
    proc { |receiver| receiver.send *self }
  end
end

# And then...

[ 'Hello', 'Goodbye' ].map &[ :+, ' world!' ]
#=> ["Hello world!", "Goodbye world!"]

Ampersand & works by sending to_proc message on its operand, which, in the above code, is of Array class. And since I defined #to_proc method on Array, the line becomes:

[ 'Hello', 'Goodbye' ].map { |receiver| receiver.send( :+, ' world!' ) }

Josh Lee's answer is almost correct except that the equivalent Ruby code should have been as follows.

class Symbol
  def to_proc
    Proc.new do |receiver|
      receiver.send self
    end
  end
end

not

class Symbol
  def to_proc
    Proc.new do |obj, *args|
      obj.send self, *args
    end
  end
end

With this code, when print [[1,'a'],[2,'b'],[3,'c']].map(&:first) is executed, Ruby splits the first input [1,'a'] into 1 and 'a' to give obj 1 and args* 'a' to cause an error as Fixnum object 1 does not have the method self (which is :first).


When [[1,'a'],[2,'b'],[3,'c']].map(&:first) is executed;

  1. :first is a Symbol object, so when &:first is given to a map method as a parameter, Symbol#to_proc is invoked.

  2. map sends call message to :first.to_proc with parameter [1,'a'], e.g., :first.to_proc.call([1,'a']) is executed.

  3. to_proc procedure in Symbol class sends a send message to an array object ([1,'a']) with parameter (:first), e.g., [1,'a'].send(:first) is executed.

  4. iterates over the rest of the elements in [[1,'a'],[2,'b'],[3,'c']] object.

This is the same as executing [[1,'a'],[2,'b'],[3,'c']].map(|e| e.first) expression.

1 upvote
  flag
Josh Lee's answer is absolutely correct, as you can see by thinking about [1,2,3,4,5,6].inject(&:+) - inject expects a lambda with two parameters (memo and item) and :+.to_proc delivers it - Proc.new |obj, *args| { obj.send(self, *args) } or { |m, o| m.+(o) } – Uri Agassi

Two things are happening here, and it's important to understand both.

As described in other answers, the Symbol#to_proc method is being called.

But the reason to_proc is being called on the symbol is because it's being passed to map as a block argument. Placing & in front of an argument in a method call causes it to be passed this way. This is true for any Ruby method, not just map with symbols.

def some_method(*args, &block)
  puts "args: #{args.inspect}"
  puts "block: #{block.inspect}"
end

some_method(:whatever)
# args: [:whatever]
# block: nil

some_method(&:whatever)
# args: []
# block: #<Proc:0x007fd23d010da8>

some_method(&"whatever")
# TypeError: wrong argument type String (expected Proc)
# (String doesn't respond to #to_proc)

The Symbol gets converted to a Proc because it's passed in as a block. We can show this by trying to pass a proc to .map without the ampersand:

arr = %w(apple banana)
reverse_upcase = proc { |i| i.reverse.upcase }
reverse_upcase.is_a?(Proc)
=> true

arr.map(reverse_upcase)
# ArgumentError: wrong number of arguments (1 for 0)
# (map expects 0 positional arguments and one block argument)

arr.map(&reverse_upcase)
=> ["ELPPA", "ANANAB"]

Even though it doesn't need to be converted, the method won't know how to use it because it expects a block argument. Passing it with & gives .map the block it expects.

upvote
  flag
This is honestly the best answer given. You explain the mechanism behind the ampersand and why we end up with a proc, which I didn’t get until your answer. Thank you. – Fralcon

It is same as below:

def tag_names
  if @tag_names
    @tag_names
  else
    tags.map{ |t| t.name }.join(' ')
end

Here :name is the symbol which point to the method name of tag object. When we pass &:name to map, it will treat name as a proc object. For short, tags.map(&:name) acts as:

tags.map do |tag|
  tag.name
end

(&:name) is short for (&:name.to_proc) it is same as tags.map{ |t| t.name }.join(' ')

to_proc is actually implemented in C

tags.map(&:name)

is The same as

tags.map{|tag| tag.name}

&:name just uses the symbol as the method name to be called.

upvote
  flag
The answer I was looking for, rather than specifically for procs (but that was the requesters question) – matrim_c

it means

array.each(&:to_sym.to_proc)

Although we have great answers already, looking through a perspective of a beginner I'd like to add the additional information:

What does map(&:name) mean in Ruby?

This means, that you are passing another method as parameter to the map function. (In reality you're passing a symbol that gets converted into a proc. But this isn't that important in this particular case).

What is important is that you have a method named name that will be used by the map method as an argument instead of the traditional block style.

Not the answer you're looking for? Browse other questions tagged or ask your own question.