You probably know about Ruby's &:method
shortcut.
Given a method name as a symbol prefixed with an &
operator, Ruby calls that method on the argument.
In the example below, Ruby calls length
on each item.
items = [ 'hi', 'hello' ]
items.map(&:length) # [2, 5]
(1..3).map(&:to_s) #=> ["1", "2", "3"]
Let's learn how this works.
Behind the Scenes
When you prefix the &
operator to a method argument, it calls to_proc
on its operand, and passes the result as a block.
You can override the to_proc
method to return a custom block, as the Person
class does below.
def bar(&block)
block.call
end
class Person
def self.to_proc
-> { puts 'hello world' }
# Proc.new { puts 'hello world' }
# proc { puts 'hello world' }
end
end
bar(&Person) # "hello world"
Now, let's override the Symbol
class to add a to_proc
method.
It will return a proc/lambda that calls the symbol (self
) on its argument (item
), using the send
method.
class Symbol
def to_proc
->(item) { item.send self }
end
end
Remember that all symbols (e.g. :item
) are instances of Symbol
. So you can call to_proc
method on a symbol like :item.to_proc
.
Now, when you pass &:some_method
to a method that accepts a proc, it calls some_method
on the argument.
The two calls below are equivalent.
items = [ 'hi', 'hello' ]
items.map(&:length) # [2, 5]
items.map { |item| item.send :length } # [2, 5]
The good news is, we don't have to monkey-patch Symbol
to add this method. Ruby already does this. This shortcut was added in ActiveSupport and became official in Ruby 1.8.7.
Pretty nice, right? Let me know in the comments below what you think.
—
I hope you liked this article and you learned something new. I sure did. If you have any questions or feedback, please send me an email. I look forward to hearing from you.
If you liked this post and would like to receive future posts directly by email, please subscribe below.
You might also enjoy these articles: