Are there special rules for naming and calling Procs? - ruby

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?

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.

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.

Related

How `[]` works with lambdas

I have this lambda (or is closure the correct usage?) and I understand the usage of .call
def multi(m)
lambda { |n| n * m }
end
two = multi(2)
two.call(10) #=> 20 #call the proc
But I am trying to understand why/how this works?
two.(20) #=> 40
two[20] #=> 40
I don't know whether it should or shouldn't work. Most of the time I have used square brackets with arrays.
The documentation
prc[params,...] → obj
Invokes the block, setting the block’s parameters to the values in params using something close to method calling semantics. Generates a warning if multiple values are passed to a proc that expects just one (previously this silently converted the parameters to an array). Note that prc.() invokes prc.call() with the parameters given. It’s a syntax sugar to hide “call”.
For procs created using lambda or ->() an error is generated if the wrong number of parameters are passed to a Proc with multiple parameters. For procs created using Proc.new or Kernel.proc, extra parameters are silently discarded.
For your first question, proc.() is a hack because Ruby doesn't let you define () on an object. It's just syntaxic sugar for proc.call().
For your second question, using square brackets on a Proc calls it.

Understanding Ruby symbol as method call [duplicate]

This question already has answers here:
How to understand symbols in Ruby
(11 answers)
Closed 10 years ago.
class A
def test
"Test from instance"
end
class << self
def test
"Test from class"
end
end
end
p A.send(:test) # "Test from class"
p A.new.method(:test).call # "Test from instance"
Here symbol works as expected, but here:
s="test"
s1=:s
p s1 # :s
why :s is printed here?? I dont understand the reason behind it.
Can anyone please explain for me ?
Symbols are sort of lightweight strings (though they are not strings). The send() and method() methods can take strings or symbols; one is converted to the other in the inner workings (not sure which) and then ruby executes the method with the matching name. Hence A.send(:text) is equivalent to A.text(). If you had a variable named methodName = :text, you could do A.send(methodName) but not A.methodName().
Symbols are not variables, so you can't assign a value to a symbol. In your example, the symbol :s is unrelated to the variable s (despite the fact that they have the same "name", preceding it with a colon makes it a symbol instead of a variable). You're assigning a string value to the variable s but telling it to print the symbol :s, which it does.
Symbols are just a special kind of stringlike value that's more efficient for the runtime to deal with than a regular string. That's it. They aren't methods or variables or anything like that.
When you do A.send(:test), all you are doing is saying "hey, A, call the method named 'test'". You aren't sending the method itself, just the name; it's the logic inside send that is responsible for looking up the actual method to call.
The same thing goes when you ask for method with A.new.method(:test). All you are passing to method is the name "test", not the method defined with that name. It's up to method to use the name and find the actual method so it can return it, and it's that return value - a Method object - that you are doing call on. You can't do call on a Symbol like :test, because it's just a name.
From https://stackoverflow.com/a/1255362/509710:
p foo does puts foo.inspect, i.e. it prints the value of inspect instead of to_s, which is more suitable for debugging (because you can e.g. tell the difference between 1, "1" and "2\b1", which you can't when printing without inspect).
s="test"
s1=:s
p :s.object_id #137448
p s.object_id #77489950
p s1.object_id #137448
I have understand it now. I was assigning a symbol but expecting a string.
You set the value of s1 to be :s, so why would you expect it to return anything different?
If you look at the ruby API for the Object class, you will see both Object#send and Object#method take a symbol as a parameter, so the top example is also totally expected.

Understanding Ruby Closures

I'm trying to better understand Ruby closures and I came across this example code which I don't quite understand:
def make_counter
n = 0
return Proc.new { n = n + 1 }
end
c = make_counter
puts c.call # => this outputs 1
puts c.call # => this outputs 2
Can someone help me understand what actually happens in the above code when I call c = make_counter? In my mind, here's what I think is happening:
Ruby calls the make_counter method and returns a Proc object where the code block associated with the Proc will be { n = 1 }. When the first c.call is executed, the Proc object will execute the block associated with it, and returns n = 1. However, when the second c.call is executed, doesn't the Proc object still execute the block associated with it, which is still { n = 1 }? I don't get why the output will change to 2.
Maybe I'm not understanding this at all, and it would be helpful if you could provide some clarification on what's actually happening within Ruby.
The block is not evaluated when make_counter is called. The block is evaluated and run when you call the Proc via c.call. So each time you run c.call, the expression n = n + 1 will be evaluated and run. The binding for the Proc will cause the n variable to remain in scope since it (the local n variable) was first declared outside the Proc closure. As such, n will keep incrementing on each iteration.
To clarify this further:
The block that defines a Proc (or lambda) is not evaluated at initialization - the code within is frozen exactly as you see it.
Ok, the code is actually 'evaluated', but not for the purpose of changing the frozen code. Rather, it is checked for any variables that are currently in scope that are being used within the context of the Proc's code block. Since n is a local variable (as it was defined the line before), and it is used within the Proc, it is captured within the binding and comes along for the ride.
When the call method is called on the Proc, it will execute the 'frozen' code within the context of that binding that had been captured. So the n that had been originally been assigned as 0, is incremented to 1. When called again, the same n will increment again to 2. And so on...
I always feel like to understand whats going on, its always important to revisit the basics. No one ever answered the question of what is a Proc in Ruby which to a newbie reading this post, that would be crucial and would help in answering this question.
At a high-level, procs are methods that can be stored inside variables.
Procs can also take a code block as its parameter, in this case it took n = n + 1. In other programming languages a block is called a closure. Blocks allow you to group statements together and encapsulate behavior.
There are two ways to create blocks in Ruby. The example you provide is using curly braces syntax.
So why use Procs if you can use methods to perform the same functionality?
The answer is that Procs give you more flexibility than methods. With Procs you can store an entire set of processes inside a variable and then call the variable anywhere else in your program.
In this case, Proc was written inside a method and then that method was stored inside a variable called c and then called with puts each time incrementing the value of n.
Similar to Procs, Lambdas also allow you to store functions inside a variable and call the method from other parts of a program.
This here:
return Proc.new { n = n + 1 }
Actually, returns a proc object which has a block associated with it. And Ruby creates a binding with blocks! So the execution context is stored for later use and hence why we can increment n. Let me go a bit further into explaining Ruby Closures, so you can have a more broader idea.
First, we need to clarify the technical term 'binding'. In Ruby, a binding object encapsulates the execution context at some particular scope in a program and retains this context for future use in the program. This execution context includes arguments passed to a method and any local variables defined in the method, any associated blocks, the return stack and the value of self. Take this example:
class SomeClass
def initialize
#ivar = 'instance variable'
end
def m(param)
lvar = 'local variable'
binding
end
end
b = SomeClass.new.m(100) { 'block executed' }
=> #<Binding:0x007fb354b7aca0>
eval "puts param", b
=> 100
eval "puts lvar", b
=> local variable
eval "puts yield", b
=> block executed
eval "puts self", b
=> #<SomeClass:0x007fb354ad82e8>
eval "puts #ivar", b
instance variable
The last statement might seem a little tricky but it's not. Remember binding holds execution context for later use. So when we invoke yield, it is invoking yield as if it was still in that execution context and hence it invokes the block.
It's interesting, you can even reassign the value of the local variables in the closure:
eval "lvar = 'changed in eval'", b
eval "puts lvar", b
=> changed in eval
Now this is all cute, but not so useful. Bindings are really useful as it pertains to blocks. Ruby associates a binding object with a block. So when you create a proc or a lambda, the resulting Proc object holds not just the executable block but also bindings for all the variables used by the block.
You already know that blocks can use local variables and method arguments that are defined outside the block. In the following code, for example, the block associated with the collect iterator uses the method argument n:
# multiply each element of the data array by n
def multiply(data, n)
data.collect {|x| x*n }
end
puts multiply([1,2,3], 2) # Prints 2,4,6
What is more interesting is that if the block were turned into a proc or lambda, it could access n even after the method to which it is an argument had returned. That's because there is a binding associated to the block of the lambda or proc object! The following code demonstrates:
# Return a lambda that retains or "closes over" the argument n
def multiplier(n)
lambda {|data| data.collect{|x| x*n } }
end
doubler = multiplier(2) # Get a lambda that knows how to double
puts doubler.call([1,2,3]) # Prints 2,4,6
The multiplier method returns a lambda. Because this lambda is used outside of the scope in which it is defined, we call it a closure; it encapsulates or “closes over” (or just retains) the binding for the method argument n.
It is important to understand that a closure does not just retain the value of the variables it refers to—it retains the actual variables and extends their lifetime. Another way to say this is that the variables used in a lambda or proc are not statically bound when the lambda or proc is created. Instead, the bindings are dynamic, and the values of the variables are looked up when the lambda or proc is executed.

Can someone explain Ruby's use of pipe characters in a block?

Can someone explain to me Ruby's use of pipe characters in a block? I understand that it contains a variable name that will be assigned the data as it iterates. But what is this called? Can there be more than one variable inside the pipes? Anything else I should know about it? Any good links to more information on it?
For example:
25.times { | i | puts i }
Braces define an anonymous function, called a block. Tokens between the pipe are the arguments of this block. The number of arguments required depends on how the block is used. Each time the block is evaluated, the method requiring the block will pass a value based on the object calling it.
It's the same as defining a method, only it's not stored beyond the method that accepts a block.
For example:
def my_print(i)
puts i
end
will do the same as this when executed:
{|i| puts i}
the only difference is the block is defined on the fly and not stored.
Example 2:
The following statements are equivalent
25.times &method(:my_print)
25.times {|i| puts i}
We use anonymous blocks because the majority of functions passed as a block are usually specific to your situation and not worth defining for reuse.
So what happens when a method accepts a block? That depends on the method. Methods that accept a block will call it by passing values from their calling object in a well defined manner. What's returned depends on the method requiring the block.
For example: In 25.times {|i| puts i} .times calls the block once for each value between 0 and the value of its caller, passing the value into the block as the temporary variable i. Times returns the value of the calling object. In this case 25.
Let's look at method that accepts a block with two arguments.
{:key1 => "value1", :key2 => "value2"}.each {|key,value|
puts "This key is: #{key}. Its value is #{value}"
}
In this case each calls the block ones for each key/value pair passing the key as the first argument and the value as the second argument.
The pipes specify arguments that are populated with values by the function that calls your block. There can be zero or more of them, and how many you should use depends on the method you call.
For example, each_with_index uses two variables and puts the element in one of them and the index in the other.
here is a good description of how blocks and iterators work
Block arguments follow all the same conventions as method parameters (at least as of 1.9): you can define optional arguments, variable length arg lists, defaults, etc. Here's a pretty decent summary.
Some things to be aware of: because blocks see variables in the scope they were defined it, if you pass in an argument with the same name as an existing variable, it will "shadow" it - your block will see the passed in value and the original variable will be unchanged.
i = 10
25.times { | i | puts i }
puts i #=> prints '10'
Will print '10' at the end. Because sometimes this is desirable behavior even if you are not passing in a value (ie you want to make sure you don't accidentally clobber a variable from surrounding scope) you can specify block-local variable names after a semicolon after the argument list:
x = 'foo'
25.times { | i ; x | puts i; x = 'bar' }
puts x #=> prints 'foo'
Here, 'x' is local to the block, even though no value is passed in.

Ruby hash value converts to string, don't know why

I have a 'strange' problem, the following code converts the location lat value into a string (With a + sign for each iteration) leading to an eventual exception when comparing values. I've tried the code with values for another location and it works fine. The only difference is that the other numbers were negatives.
location= {:lng => 2.0781,:lat => 41.2899}
while location[:lat] < top
sleep(1)
checkTweets(location)
bottom+=0.075
location[:lat] = bottom
end
The issue occurs before entering the check tweets location. The values for the hash are as follows
To to conclude, my question is can anyone explain to me why location[:lat] ends up being a string in this circumstance?
Bottom is initialized as 30.0400 which is assigned to the :lat value. The checkTweets method simply writes a file based on a mongodb query.
Right I found the solution to this. It was the twitter library which was turning the Hash float values into strings.
Am I wrong in assuming that the scope of the variable in the checkTweets method should not impact the location variable here, they are both declared in seperate methods, they are not class level.
I wrong in assuming that the scope of the variable in the checkTweets method should not impact the location variable here, they are both declared in seperate methods, they are not class level.
No, but variable scope is not the issue here. The location variable is local to your method and as such cannot be changed by the checkTweets method. That is correct.
However the object that is referenced by the location variable can be changed from the checkTweets method and that is exactly what happens (though I have to say that mutating arguments is very bad style).
A little example to illustrate reference semantics and mutation in ruby:
def f1(arr)
arr = [1,2,3] # Changes the variable arr, which is local to f1
# This change is not visible on the outside
end
def f2(arr)
arr.concat [1,2,3] # Changes the object that arr refers to
# This change will be visible any place where the same
# array is referenced
end
foo = [42,23]
f1(foo)
# foo is still [42, 23]
f2(foo)
# foo is now [42, 23, 1, 2, 3]
Here the variable foo hasn't been changed to refer to another object (that would not be possible from inside a method), but the object that foo refers to has been changed. The same happens in your checkTweets method.

Resources