I noticed while learning Ruby that both of these uses of the each method work and produce the same output, and I was wondering how Ruby makes this happen (and how I can make it happen for my own functions):

my_array = [["hello","goodbye"],["picture","perfect"]]

my_array.each do |array|

  puts array[0] + " " + array[1]

end

my_array.each do |first, second|

  puts first + " " + second

end

My understanding is that when writing the definition of a method that accepts a code block, the yield method is utilized to pass arguments to the code block and call the block. But how can you utilize the yield method such that it passes different arguments depending on the provided code block? In the example case, it appears that the yield method passes the individual array elements when two parameters (i.e., first, second) are used within the block, and it passes the arrays themselves when one parameter is used within the block (i.e., array).

有帮助吗?

解决方案

Neither each not yield are doing anything special here, that's just how block arguments work. Consider this simple example:

def f(x) yield x end

and now we can see what happens:

>> f([1,2]) { |a| puts a.inspect }
[1, 2]
>> f([1,2]) { |a, b| puts "#{a} - #{b}" }
1 - 2
>> f([1,2]) { |a, b, c| puts "#{a} - #{b} - #{c}" }
1 - 2 - 

You'll see similar destructing in assignments:

a, b = [1, 2]

You can also do it explicitly with a splat:

a, b = *[1, 2]

or like this:

def g(x) yield *x end
g([1, 2]) { |a, b| puts "#{a} - #{b}" }

Presumably the block knows what sorts of things it will be given so the block is well positioned to unpack the arguments. Note that the g function has to know that its argument is splatable (i.e. an array) but f doesn't. f nicely puts the "what sort of thing is x" logic together in the call to f, g buries half of the logic inside itself. One place where the difference becomes apparent is when you use Enumerable methods on a Hash:

{ :where => :is, :pancakes => :house? }.map { |k, v| ... }

Enumerable#map doesn't need to know that a Hash works in key/value two element arrays, it just passes things around and leaves it up everyone else to worry about the details.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top