I wanted to create this array
["studies", "theory", "form", "animal", "basic", "processes"]
from the following nested data structure (stored as sorted_hash
):
[["studies", {:freq=>11, :cap_freq=>0, :value=>11}],
["theory", {:freq=>9, :cap_freq=>1, :value=>11}],
["form", {:freq=>9, :cap_freq=>1, :value=>11}],
["animal", {:freq=>12, :cap_freq=>0, :value=>12}],
["basic", {:freq=>10, :cap_freq=>1, :value=>12}],
["processes", {:freq=>13, :cap_freq=>0, :value=>13}]]
I confused this to be a hash and wrote the following code to achieve my task:
sorted_hash.each do |key,value|
array.push key
end
And I really got what I wanted. But after some thinking and playing around in Pry I wonder why. The each
method Ruby Doc for Arrays only shows examples with one item variable, as in
each { |item| block } → ary
but I use two variables as I would do for Hashes. Will Ruby try to match the given item variables, which in this case succeeds as the 2nd level array has a length of 2? Is it recommendable to do it like that? Are there more idiomatic ways to do it?
That's because Ruby conveniently lets you do this:
So basically,
each
yields an array element to the block, and because Ruby block syntax allows "expanding" array elements to their components by providing a list of arguments, it works.You can find more tricks with block arguments here.
And by the way, instead of creating an array yourself and calling
push
, you can simply do the following, sincemap
returns an array:The answer follows from the way "parallel assignment" is implemented in Ruby.
As you probably know:
The last two examples employ "disambiguation", which some people prefer to call "decomposition".
Now let's see how that applies to the assignment of values to block variables.
Suppose:
and we execute:
Let's look at this more carefully. Define:
The first element is passed to the block and assigned to the block variable
v
:We may be prefer to use parallel assignment with two block variables (after
enum.rewind
to reset the enumerator):That allows us to write (for example):
Here we do not use the block variable
a
. When that is the case, we might replace it with the local variable_
or possibly_a
:This draws attention to the fact that
a
is not used and may help to avoid errors. Regarding errors, suppose we want:but inadvertently write:
which executes just fine (but produces an incorrect result). By contrast,
tells us there's a problem.
Here's a more elaborate example of what you can do in blocks with parallel assignment and disambiguation. Given:
suppose we wish to obtain:
One way is the following: