Block with two parameters

I found this code by Hirolau user:

def sum_to_n?(a, n) a.combination(2).find{|x, y| x + y == n} end a = [1, 2, 3, 4, 5] sum_to_n?(a, 9) # => [4, 5] sum_to_n?(a, 11) # => nil 

How do I know when I can send two parameters to a predefined method like find ? I don’t understand this, because sometimes it doesn’t work. Is this something that has been redefined?

+5
source share
3 answers

If you look at the Enumerable#find documentation, you will see that it takes only one parameter per block. The reason you can send it two is because Ruby allows you to do this with blocks based on a "parallel assignment" structure:

 [[1,2,3], [4,5,6]].each {|x,y,z| puts "#{x}#{y}#{z}"} # 123 # 456 

Thus, each of them gives an array element to a block, and since the Ruby block syntax allows you to "expand" the array elements to their components by providing a list of arguments, it works.

You can find more tricks with block arguments here .

a.combination(2) leads to an array of arrays, where each of the subvariant arrays consists of two elements. So:

 a = [1,2,3,4] a.combination(2) # => [[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]] 

As a result, you send one array, for example [1,2] , to find the block, and Ruby performs a parallel assignment to assign from 1 to x and from 2 to y .

Also see this SO question for other powerful examples of parallel assignment such as this statement:

 a,(b,(c,d)) = [1,[2,[3,4]]] 
+6
source

find does not accept two parameters, it accepts one. The reason the block in your example takes two parameters is because it uses destruction. The previous a.combination(2) code gives an array of arrays of two elements, and find iterates over it. Each element (an array of two elements) is passed at a time to the block as its only parameter. However, when you write more parameters than there are, Ruby tries to adjust the parameters by destroying the array. Part:

 find{|x, y| x + y == n} 

is short for record:

 find{|(x, y)| x + y == n} 
+3
source

The find function iterates over the elements, it takes one argument, in this case a block (which takes two arguments for the hash):

 h = {foo: 5, bar: 6} result = h.find {|k, v| k == :foo && v == 5} puts result.inspect #=> [:foo, 5] 

A block takes only one argument for arrays, but if you are not using destructuring.

Update: it seems that in this case it is destroying.

0
source

Source: https://habr.com/ru/post/1236185/


All Articles