Reputation: 45
I completed a Ruby challenge on Hacker Rank, but I don't understand why a Proc is able to be called with an abbreviated version of its saved name.
The proc was defined as:
proc_sum_array = proc {|arr| arr.reduce(:+)}
But it was called like this:
proc_sum.call(my_array)
...without the "_array" part of the name proc_sum_array
This confused me, so I changed 'proc_sum.call(my_array)' to 'proc_sum_array.call(my_array)' but then I got the error:
undefined local variable or method `proc_sum_array' for main:Object (NameError)
Did you mean? proc_sum
So it appears that it is important that the proc is called as proc_sum and not proc_sum_array, as it was named.
def square_of_sum (my_array, proc_square, proc_sum)
sum = proc_sum.call(my_array) # QUESTION: Why is this proc_sum, and not proc_sum_array ?
proc_square.call(sum)
end
proc_square_number = proc {|x| x ** 2}
proc_sum_array = proc {|arr| arr.reduce(:+)} # This is where the proc is defined.
my_array = gets.split().map(&:to_i)
puts square_of_sum(my_array, proc_square_number, proc_sum_array)
I would expect that proc_sum_arry would be called as proc_sum_array.call. Why is this not the case?
Upvotes: 0
Views: 65
Reputation: 51161
Ok, now as you linked actual example, I can answer you.
The reason why it's referred to as proc_sum
, not proc_sum_array
is because it's how the argument passed into square_of_sum
method is named. It's not magical at all. It's similar to:
a = 2
def sqr(b)
b * b
end
sqr(a)
You see, you define a
local variable, but you pass it as b
argument in the sqr
method, so inside of this method you refer to it as b
.
Upvotes: 1
Reputation: 369468
This is called a parameter. A parameter is kind of like a "hole" that you leave in the definition of a subroutine. When you invoke that subroutine, you "fill" that "hole" with an argument. (This is called "passing an argument".)
Here:
def square_of_sum (my_array, proc_square, proc_sum)
# ↑↑↑↑↑↑↑↑
You define a method named square_of_sum
with a couple of parameters. The third one of those parameters is called proc_sum
.
Here:
puts square_of_sum(my_array, proc_square_number, proc_sum_array)
# ↑↑↑↑↑↑↑↑↑↑↑↑↑↑
You pass the object that is referenced by the local variable proc_sum_array
as an argument to the invocation of the square_of_sum
method.
What this means is that inside the body of the method, the object that you passed as an argument will be bound to the parameter (this is called binding an argument to a parameter), i.e. when you dereference the parameter proc_sum
inside the body of square_of_sum
, it will evaluate to whatever object was passed as an argument.
Note that proc_sum_array
is a local variable (you know that it is a local variable because 1) it starts with a lowercase letter and 2) it is not a method). Local variables are called "local" variables because they are local to the scope they are defined in. In this particular case, proc_sum_array
is local to the script scope, which means that it doesn't even exist inside the method scope of square_of_sum
, so you simply can't refer to it at all!
Note also that this is exactly the same as for every other parameter of square_of_sum
: you refer to the object that is passed as an argument for the proc_square
parameter as proc_square
and not as proc_square_number
.
Upvotes: 3