The answer follows from how Ruby implements "parallel assignment."
As you probably know:
a,b,c = 1,2,3 a
The last two examples use "ambiguity," which some people prefer to call "decomposition."
Now let's see how this relates to assigning values ββto lock variables.
Let's pretend that:
arr = [["studies", {:freq=>11, :cap_freq=>0, :value=>11}], ["theory", {:freq=>9, :cap_freq=>1, :value=>11}]]
and execute:
arr.each { |a| pa } ["studies", {:freq=>11, :cap_freq=>0, :value=>11}] ["theory", {:freq=>9, :cap_freq=>1, :value=>11}]
Look at it more closely. Definition:
enum = arr.each #=> #<Enumerator: [["studies", {:freq=>11, :cap_freq=>0, :value=>11}], # ["theory", {:freq=>9, :cap_freq=>1, :value=>11}]]:each>
The first element is passed to the block and assigned to the block variable v :
v = enum.next #=> ["studies", {:freq=>11, :cap_freq=>0, :value=>11}]
We may prefer to use a parallel assignment with two block variables (after enum.rewind to reset the enumerator):
a,h = enum.next a #=> "studies" h #=> {:freq=>11, :cap_freq=>0, :value=>11}
This allows us to write (for example):
arr.each { |a,h| ph } {:freq=>11, :cap_freq=>0, :value=>11} {:freq=>9, :cap_freq=>1, :value=>11}
Here we do not use the block variable a . If so, we can replace it with the local variable _ or perhaps _a :
arr.each { |_,h| ph } arr.each { |_a,h| ph }
This draws attention to the fact that a not used and can help avoid errors. As for errors, suppose we want:
[[1,2],[3,4]].map { |a,b| puts 1+b } #=> [3,5]
but inadvertently write:
[[1,2],[3,4]].map { |a,b| puts a+b } #=> [3,7]
which only fines (but produces an incorrect result). On the contrary
[[1,2],[3,4]].map { |_,b| puts a+b } #NameError: undefined local variable or method 'a'
indicates a problem.
Here is a more detailed example of what you can do in blocks with parallel assignment and values. Given:
h = { :a=>[1,2], :b=>[3,4] }
suppose we want to get:
{ :a=>3, :b=>7 }
One of the methods:
h.each_with_object({}) { |(a,(b,c)),g| g[a] = b+c } => {:a=>3, :b=>7}