My memory got the worst of me and I forgot about Array#find.
So I wrote some code which used Array#first to get the first item matching a condition:
first_even_num = [1,2,3].first { |x| x % 2 == 0 }
This does not work, it just returns the first element of the array no matter what the condition is. The block is not being called at all:
[1,2,3].first { |x| exit }
puts "the program did not exit"
I've accepted that Array#first does not do what imagined it to, but I'm curious why the aforementioned examples don't raise errors.
Looking at the 2.3.1 source, the only documented argument is an integer representing the number of returned results.
I don't really know C but this is what the underlying Array#first method has as a parameter signature:
rb_ary_first(int argc, VALUE *argv, VALUE ary)
I'm just wondering why the block provided to Array#first does not raise an error if it does nothing.
You can pass blocks to any method, absolutely any. If it doesn't need the block, it simply won't use it. It is not an error (because block is not one of the arguments. It's a separate input for a method)
There's some simple rules about Ruby and blocks.
You can pass a block to any method.
That method may choose to run your block zero or more times at any point in time from the present to the distant future.
You must read the documentation or method implementation to understand if, how and when a block will be exercised. There is no other way of knowing.
Your example here of passing a block to a method that's not expecting one is consistent with these rules. Effectively it's being run zero times and has no bearing on the outcome of the first call.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With