Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Number of arguments in a ruby block

Tags:

ruby

lambda

I'm new to Ruby, but not to languages that allow lambda's, such as groovy. So I saw this example:

myArray.product(otherArray).reject{|i,j| i > j}

in a ruby code block, and I hadn't seen this block take 2 arguments before, but when I went to look at the documentation I can only see the documentation that says that it takes 1 argument. I looked at the same for the enumerable class, but that doc only shows 1 argument also.

I understand that it works, I guess I was hoping that there was an easier way to determine how many arguments it takes other then a guess and test method. How can I tell how many arguments a block takes in Ruby?

like image 315
Nicholas Avatar asked Dec 11 '22 19:12

Nicholas


2 Answers

This works because Ruby supports destructuring.

Destructuring allows you to bind a set of variables to a corresponding set of values anywhere that you can normally bind a value to a single variable.

This allows the following to hold true:

arr = [1, 2]
x = arr
x == [1, 2] # true

y, z = arr
y == 1 # true
z == 2 # true

You can see from the following code that destructuring in arguments to blocks isn't unique to the built-in methods that take a block:

def my_method(arr)
  yield arr
end

my_method([1, 2, 3]) {|x| puts x.inspect }
# => [1, 2, 3]
my_method([1, 2, 3]) {|x, y, z| puts x.inspect }
# => 1

Check out Destructuring with Ruby for more information.

like image 143
Michelle Tilley Avatar answered Dec 21 '22 00:12

Michelle Tilley


You can do some interesting restructuring in block parameters, depending on the structure of your array:

[[1, 2], [3, 4], [5, 6], [7, 8]].reject {|x,y| y == 8 }
#=> [[1, 2], [3, 4], [5, 6]]

You can group them in parentheses:

[ [[1,2],3], [[1,3],6] ].select {|(x,y),z| x == 1 && z == 3 }
#=> [ [[1,2],3] ]

You can also use the splat operator for various things, like dealing with variable-length subarrays:

[[:a,:b,2,3,4,5,6], [:c,:d,7,8,9]].each {|x,y,*numbers| puts numbers.inspect }
#=> [2,3,4,5,6]
#=> [7,8,9]
like image 29
Zach Kemp Avatar answered Dec 20 '22 22:12

Zach Kemp