When you have a simple array, the following things happen:
arr = [1,2,3,4] arr.each do |x| px end 1 2 3 4 => [1,2,3,4] arr.each do |x,y| px py end 1 nil 2 nil 3 nil 4 nil => [1,2,3,4]
therefore, if ruby does not know what to put in the block argument, it simply sets it to nil . Now consider a nested array:
arr = [[1,2],[3,4],[5,6]] arr.each do |x| px end [1, 2] [3, 4] [5, 6] => [[1,2],[3,4],[5,6]] arr.each do |x,y| px py end 1 2 3 4 5 6 => [[1,2],[3,4],[5,6]]
In this case, ruby assumes that you want to assign two elements of internal arrays to the block variables x and y . The same goes for hashes, where Ruby assigns the key and value to x and y :
hash = {1 => 2, 3 => 4, 5 => 6} hash.each do |x,y| px py end 1 2 3 4 5 6 => {1=>2,3=>4,5=>6}
If you do not have enough elements in nested arrays, the block variables are assigned nil . When there are too many of them, they are simply discarded:
arr = [[1,2,3],[4,5],[6]] arr.each do |x,y| px py end 1 2 4 5 6 nil => [[1,2,3],[4,5],[6]]
quite simple!
EDIT
As for your edited question: no, you cannot apply this 1: 1 code to Ruby, you will have to manually apply the splat ( * ) operator to subcats . Thus, ruby assigns all remaining elements to the "splatted" block variable:
categories.each do |category,*subcats| puts "The main category is #{category} and the sub categories are: " subcats.each do |subcat| puts "#{subcat}, " end end
although I would generate a list of subcategories separated by commas:
categories.each do |category,*subcats| puts "The main category is #{category} and the sub categories are: " puts subcats.join(', ') end
EDIT 2 :
Oh, and you won’t process a huge ugly multidimensional array by defining many block parameters for your elements. You could probably iterate over it using nested loops, like in any other language, if only because you never know how many elements it contains.