Mr. Kennedy Mr. Kennedy - 27 days ago 4
Ruby Question

Yield variable scope with Ruby

How does Ruby distinguish the codeblocks

|n|
's in the functions yield case of "Kim" and the function call's case of "Eric"?

Apologies if this is painfully obvious - I really don't see how exactly the
|n|
variable in the codeblock with the function(arg) call effects the functions internal yield call?

def yield_name(name)
puts "In the method! Let's yield..."
yield("Kim")
puts "... now in between the yields!"
yield(name)
puts "Block complete! Back in the method."
end




>>> yield_name("Eric") { |n| puts "My name is #{n}." }





In the method! Let's yield...
My name is Kim.
... now in between the yields!
My name is Eric.
Block complete! Back in the method.



As I understand the code block, it reads, "for each argument, put to screen "My name is #{that argument}". How does Ruby pass "Kim" into "that argument" so it prints "My name is Kim" instead of just "Kim"? Thank you.

---------------------- EDIT

Here's a less confusingly named example:

def double(parameter)
yield parameter
yield 7
end



When I invoke:


>>> double(3) { |n| puts "how? #{n * 2}" }



I get:



how? 6 #<-- relative to function call(arg)
how? 14 #<-- relative to internal functions yield call(arg)



So how does Ruby know to use yield 7 in the puts statement ?

Answer

As I understand the code block, it reads, "for each argument, put to screen "My name is #{that argument}"

Nope. Literally, it reads "pass argument 'Eric' to method yield_name and also pass this block". The mere fact that you passed a block to method means nothing. The method can simply just not call it (also known as "yielding to block"). So you can't make any assumptions about number of block invocations or values of supplied parameters without knowing implementation of the method.

In this case, we do know the implementation

def yield_name(name)
  puts "In the method! Let's yield..."
  yield("Kim")
  puts "... now in between the yields!"
  yield(name)
  puts "Block complete! Back in the method."
end

Here we see that per each call, yield_name calls its block two times. First, with a static value ("Kim"). Second time, it simply relays its parameter name. If there were no yield statements here, the block you supplied would be completely ignored (and, therefore, nothing would be printed). But we do trigger the block two times and see two lines in the output.