Ruby ampersand colon shortcut
Your question is wrong, so to speak. What's happening here isn't "ampersand and colon", it's "ampersand and object". The colon in this case is for the symbol. So, there's &
and there's :foo
.
The &
calls to_proc
on the object, and passes it as a block to the method. In Ruby, to_proc
is implemented on Symbol
, so that these two calls are equivalent:
something {|i| i.foo }
something(&:foo)
So, to sum up: &
calls to_proc
on the object and passes it as a block to the method, and Ruby implements to_proc
on Symbol
.
Is it possible to use &: (ampersand colon) notation with a parameter or with chaining in Ruby?
:to_s
is a symbol,not a method. So you can't pass any argument to it like :to_s(2)
. If you do so,you will get error.That's how your code wouldn't work.So [1, 2, 3].map(&:to_s(2))
is not possible,where as [1, 2, 3].map(&:to_s)
possible.&:to_s
means you are calling #to_proc
method on the symbol. Now in your case &:to_s(2)
means :to_s(2).to_proc
. Error will be happened before the call to the method #to_proc
.
:to_s.to_proc # => #<Proc:0x20e4178>
:to_s(2).to_proc # if you try and the error as below
syntax error, unexpected '(', expecting $end
p :to_s(2).to_proc
^
Now try your one and compare the error with above explanation :
[1, 2, 3].map(&:to_s(2))
syntax error, unexpected '(', expecting ')'
[1, 2, 3].map(&:to_s(2))
^
What do you call the &: operator in Ruby?
There's a few moving pieces here, but the name for what's going on is the Symbol#to_proc
conversion. This is part of Ruby 1.9 and up, and is also available if you use later-ish versions of Rails.
First, in Ruby, :foo
means "the symbol foo
", so it's actually two separate operators you're looking at, not one big &:
operator.
When you say foo.map(&bar)
, you're telling Ruby, "send a message to the foo
object to invoke the map
method, with a block I already defined called bar
". If bar
is not already a Proc
object, Ruby will try to make it one.
Here, we don't actually pass a block, but instead a symbol called bar
. Because we have an implicit to_proc
conversion available on Symbol
, Ruby sees that and uses it. It turns out that this conversion looks like this:
def to_proc
proc { |obj, *args| obj.send(self, *args) }
end
This makes a proc
which invokes the method with the same name as the symbol. Putting it all together, using your original example:
array.map(&:to_i)
This invokes .map
on array, and for each element in the array, returns the result of calling to_i
on that element.
What does &. (ampersand dot) mean in Ruby?
It is called the Safe Navigation Operator. Introduced in Ruby 2.3.0, it lets you call methods on objects without worrying that the object may be nil
(Avoiding an undefined method for nil:NilClass
error), similar to the try
method in Rails.
So you can write
@person&.spouse&.name
instead of
@person.spouse.name if @person && @person.spouse
From the Docs:
my_object.my_method
This sends the
my_method
message tomy_object
. Any
object can be a receiver but depending on the method's visibility
sending a message may raise aNoMethodError
.You may use
&.
to designate a receiver, thenmy_method
is not invoked
and the result isnil
when the receiver isnil
. In that case, the
arguments ofmy_method
are not evaluated.
What does map(&:name) mean in Ruby?
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
what does &: mean in ruby, is it a block mixed with a symbol?
When &
used before Proc object in method invocation, it treats the Proc as if it was an ordinary block following the invocation.
When &
used before other type of object (symbol :first_name
in your case) in method invocation, it tries to call to_proc on this object and if it does not have to_proc method you will get TypeError
.
Generally &:first_name
is the same as &:first_name.to_proc
.
Symbol#to_proc Returns a Proc object which respond to the given method by sym.
:first_name.to_proc
will return Proc that looks like this:
proc { |obj, *args, &block| obj.first_name(*args, &block) }
this Proc invokes method specified by original symbol on the object passes as the first parameter and pass all the rest parameters + block as this method arguments.
One more example:
> p = :each.to_proc
=> #<Proc:0x00000001bc28b0>
> p.call([1,2,3]) { |item| puts item+1 }
2
3
4
=> [1, 2, 3]
What does this ampersand mean?
It's basically shorthand for this:
[Category, Product, Person].each { |e| e.delete_all }
That is, it sends delete_all
to each element of the iterator.
What does map(&:name) do in this Ruby code?
events.map(&:name)
is exactly equivalent to
events.map{|x| x.name}
it is just convenient syntactic sugar.
For more details, check out the Symbol#to_proc
method here. Here, :name
is being coerced to a proc.
By the way, this comes up often here - it's just very hard to google or otherwise search for 'the colon thing with an ampersand' :).
what is the functionality of &: operator in ruby?
There isn't a &:
operator in Ruby. What you are seeing is the &
operator applied to a :symbol
.
In a method argument list, the &
operator takes its operand, converts it to a Proc
object if it isn't already (by calling to_proc
on it) and passes it to the method as if a block had been used.
my_proc = Proc.new { puts "foo" }
my_method_call(&my_proc) # is identical to:
my_method_call { puts "foo" }
So the question now becomes "What does Symbol#to_proc
do?", and that's easy to see in the Rails documentation:
Turns the symbol into a simple proc, which is especially useful for enumerations. Examples:
# The same as people.collect { |p| p.name }
people.collect(&:name)
# The same as people.select { |p| p.manager? }.collect { |p| p.salary }
people.select(&:manager?).collect(&:salary)
Related Topics
How to Use the Conditional Operator (? :) in Ruby
How to Convert a String Object into a Hash Object
How to Modify Path For Homebrew
Getting the Hostname or Ip in Ruby on Rails
How to Avoid Tripping Over Utf-8 Bom When Reading Files
Saving Enum from Select in Rails 4.1
Ruby 1.9: How to Properly Upcase & Downcase Multibyte Strings
Finding the Cause of a Memory Leak in Ruby
Rvm and Thin, Root Vs. Local User
How to Understand Nil Vs. Empty Vs. Blank in Ruby
What Is the Colon Operator in Ruby
Best Way to Escape and Unescape Strings in Ruby