I came across the &method in a codebase and I have no idea what is going on. This happens in irb:
[12,3].map(&method(:to_s))
#=> ArgumentError: wrong number of arguments (given 1, expected 0)
["12","3"].map(&method(:Integer))
#=> [12, 3]
What is going on here?
I'm familiar with & being equal to to_proc, but I still can't connect the dots here.
In &method(:to_s), .to_s is taken from current context (top level object main). This version is already bound to receiver and does not accept further arguments. But an argument will be passed by .map (each element of the array), that's what it does.
Take a look at this step-by-step reconstruction of what's happening
to_s # => "main"
method(:to_s) # => #<Method: main.to_s>
method(:to_s).to_proc # => #<Proc:0x007ff73a27e1e0 (lambda)>
method(:to_s).to_proc.call(12) # =>
# ~> -:6:in `to_s': wrong number of arguments (given 1, expected 0) (ArgumentError)
# ~> from -:6:in `<main>'
Now compare to what would happen if it was .map(&:to_s)
:to_s.to_proc.call(12) # => "12"
I came across the
&methodin a codebase
It can be useful in situations like this: apply a piece of logic to each element, but this logic comes from the current context, completely external to the elements. Take a look at this contrived example:
class Tweet
attr_accessor :text
def initialize(text)
@text = text
end
def shortened_links
find_links.map(&method(:shorten_link))
# same as
# find_links.map {|link| shorten_link(link) }
end
private
def find_links
# detect links in text
end
def shorten_link(url)
# use bit.ly or whatever
end
end
Here links is a collection of strings. They most certainly can't shorten themselves.
Here is your code where & literal replaced by appropriate block:
[12,3].map { |v| to_s(v) }
["12","3"].map { |v| Integer(v) }
When it called in console, to_s and Integer are methods in Object class. (Technically Integer() is from Kernel, that is included in Object).
to_s definition has no arguments, that is why you get ArgumentError.
Integer method could accept 1 or 2 arguments.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With