11. Symbols, Meets Procs


I have he correct code for this question (below) but I don't understand the purpose of this exercise. What symbol was converted to a proc? Why does the &: have to be used...couldn't string.map(to_i) achieve the same outcome?

Symbols, Meet Procs
Now that you're learning some of the more complex parts of the Ruby language, you can combine them to work some truly arcane magicks. For instance, remember when we told you that you could pass a Ruby method name around with a symbol? Well, you can also convert symbols to procs using that handy little &.

Check it out:

strings = ["1", "2", "3"]
nums = strings.map(&:to_i)

==> [1, 2, 3]

By mapping &:to_i over every element of strings, we turned each string into an integer!


Hey @supasuma

That's a pretty good question, and it took me a little while to properly wrap my head around how it works myself when I tried searching for an answer, but I will try my best to explain it.

First, the map method. According to the ruby source, this method wants a block as parameter, such as {|paramName| puts "Do something" }. Blocks are essentially the same as procs, with the exception of them not being objects and therefore can't be saved in a variable.

Second, the & operator. It will convert a block into a proc, or a proc into a block, depending on what the object it's being used with.
So, taking the sample code below, we create a simple array of some letters, create a simple proc that will output a value, and then pass it to the map function (adding & in front of the proc variable to convert it to a block). Then I illustrate the same use through a block

my_array = ["3", "1", "2"]
my_proc = proc {|item| print item}
#output = 312
my_array.map {|item| print item}
#output = 312

Thirdly, the :to_i. This is a symbol of the method to_i, which the String class have for converting the string into an integer. You can get this through other means, such as executing "someString".method("to_i").name, which will return the symbol for the same method (in this example :to_i). But since we already know the method, we can write the symbol directly.

Now, I mentioned in the second step that & will convert blocks to proc, and procs to blocks, but :to_i is a symbol. However, when the & operator is used on something neither a block or proc, it will try to call the to_proc method, which the symbol class has.
I haven't been able to find a site that shows directly what the to_proc will return, but I guess it would be similar to this:
proc {|item| item.send(:my_symbol)}
.send(symbol) is a way of calling a method through it's symbol name

This proc is then converted to a block due to the & operator, and passed to the .map method as a parameter.

Now, the reason as to why it has to be written like .map(&:to_i) instead of just .map(to_i), I can't technically answer, but I guess it must be because of the underlying logic of the language itself in regards to blocks, procs and symbols.

Now, I have added some script below that can demonstrate a bit of the different interactions of procs and symbols in regard to the .map method, to hopefully illustrate a bit more properly how it all works

p my_array = ["3", "1", "2"]
#output = ["3", "1", "2"]
#Here I create a simple array, and output it to the console using 'p' (Which is shorthand running .inspect on an object before calling puts. Inspect, as quoted by the ruby documentation, "Returns a string containing a human-readable representation of obj")

p my_array.map(&:to_i)
#output = [3, 1, 2]
#Here we do the simple demonstration that you used in the lesson.

p my_array = ["1", "2", 3]
#output = ["1", "2", 3]
#Here we reassign the array variable with a new one, but take note that the last value is an integer instead of a string

#p my_array.map(&:capitalize)
#output = undefined method `capitalize' for 3:Fixnum
#This is to demonstrate that the symbol, in this case :capitalize, is found of the object used in the block. Since only string has the capitalize method, the integer (aka Fixnum), will throw an error

p my_proc = proc {|x| x*2}
#output = #<Proc:0x0000000195e538@(repl):17>
#This is the output of the proc object. It doesn't really give much information, besides telling you it is a Proc object

p my_array.map(&my_proc)
#output = ["11", "22", 6]
#Now we pased the custom proc to the map function, using & in order to convert it from a proc into a block. The output values are simply how a string corresponds to being multiplied with a number.

p my_array = ["hello", "hey there", "howdy"]
#output = ["hello", "hey there", "howdy"]
#Just reassigning the variable to a new array of only string objects

p string_method = "Somestring".method("capitalize")
#output = #<Method: String#capitalize>
#Her we fetch the method capitalize that belongs to the string object

p capitalize_symbol = string_method.name
#output = :capitalize
#Here we get the symbol of the method, which has the same structure as the symbol :to_i we used earlier

p my_array.map(&capitalize_symbol)
#output = ["Hello", "Hey there", "Howdy"]
#Here we send along the symbol of capitalize, which Ruby will run to_proc on in order to get a proc object to convert to a block for the map method

p capitalize_proc = capitalize_symbol.to_proc
#output = #<Proc:0x000000025f84b0>
#Here we run the to_proc method ourselves, and can see that the object is a proc, similar to the one we made ourselves

p my_array.map(&capitalize_proc)
#output = ["Hello", "Hey there", "Howdy"]
#Here we send the proc object ourselves instead of the symbol, but since the map function requires a block, we still need the & operator in order to convert the proc into a block

I hope I made myself understandable, but let me know if something is unclear and I'll try to clarify it, or if you have any other questions.


numbers_array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

strings_array = numbers_array.map(&:to_s)


I'm not understanding this. I get how each element in the array was converted from an integer to a string, but the lesson's title is "Symbols, Meets Procs.

Nowhere in this do I see symbols or procs. I only see an array of numbers that were converted to strings.

Can someone please explain. Am I missing something?