Issue
This works:
strings = ["1", "2", "3"]
nums = strings.map(&:to_i)
We see that & (to_proc method) applied to a Symbol object is turned into a block. This, however, doesn't work:
strings = ["1", "2", "3"]
nums = strings.map(&to_i)
nums = strings.map("to_i".to_sym.to_proc) #...neither does this
Why doesn't it work? Isn't there any alternative way to write the code above? I'm confused because there are two ways to access a method of a class:
"1".method(:to_i).call #works as well as
"1".method("to_i").call
So the method's name can be accessed either by symbol or a string.
Solution
Given the following valid Ruby example:
"to_i".to_sym.to_proc.call("1")
To call #to_proc
on a Symbol creates a proc that receive one parameter: the object that should receive an invocation of the method named by the symbol. Something like this:
->(object) {
object.send(:to_i)
}
What the &
do is to pass the block returned by #to_proc
as a proper invocation block to the method being called. When used with Enumerable#map
, the final result is that the passed
block will be invoked for each element on the collection and receive
the current iteration element being passed as parameter to the block.
So the ["1", "2"].map(&:to_i)
syntax is a shortcut to something like
this:
block = ->(el) {
el.send(:to_i)
}
["1", "2"].map &block
About your examples:
When you try to call &to_i
in your example, Ruby will try to invoke
a variable or method named to_i
. Since it doesn't exists in the
scope (it is a method of each String
in the Array
, not in the "global" scope), it'll generate an error.
About the other example: "to_i".to_sym.to_proc
will transform the
:to_i
into a proc that when invoked with one parameter, will try to
call the method named after the symbol (:to_i
) against the target
parameter. This means that you could use the &
to transform the proc
into a "invocation block":
["1", "2"].map(&"to_i".to_sym.to_proc)
Answered By - Ricardo Valeriano Answer Checked By - Willingham (PHPFixing Volunteer)
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.