Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby's find method - argument?

I'm doing a bit of exploring. Concerning Ruby's

.find(ifnone = nil) { |obj| block } 
method: from reading the documentation, it seems to me that you are supposed to be able to pass a method as an argument that will be run in the case that there are no matches for the specified conditions.

It says:

"calls ifnone and returns its result when it is specified, or returns nil otherwise."

This seems to work with any method I create that already returns nil, say:

 
def message
 puts 'No match.'
end
No match.
=>nil

If I use a method that does return something, say:

def message
 p 'No match.'
end

I'll get:

"No match."
NoMethodError: undefined method `call' for "No match.":String

Would someone be kind enough to explain to me precisely what kind of arg/method is actually supposed to be passed to the find method here? Thanks.

like image 303
Nathaniel Miller Avatar asked Nov 05 '15 03:11

Nathaniel Miller


People also ask

What is a Ruby argument?

In Ruby, all arguments are required when you invoke the method. You can't define a method to accept a parameter and call the method without an argument. Additionally, a method defined to accept one parameter will raise an error if called with more than one argument. def greeting(name) puts "Hello, #{name}!"

How do you call a method in an argument?

Instead, we can call the method from the argument of another method. // pass method2 as argument to method1 public void method1(method2()); Here, the returned value from method2() is assigned as an argument to method1() . If we need to pass the actual method as an argument, we use the lambda expression.

How do you accept number of arguments in Ruby?

A method defined as def some_method(**args) can accept any number of key:value arguments. The args variable will be a hash of the passed in arguments.


1 Answers

I'm glad you asked this question. I never thought about that argument for the find method because I never really had to use it before. I instead always ignored it until you mentioned it here.

The argument you would pass to an enumerable, like find, would be a lambda or proc. Rather than returning the default nil if no matches were found, it would return the lambda/proc.

So a quick example:

nums = [1, 2, 3, 4]
nums.find(lambda {raise ArgumentError, "No matches found"}) { |num| num == 5 }

> ArgumentError: No matches found

Also similarly, you can pass a Proc as well..

nums = [1, 2, 3, 4]
arg = Proc.new {"No matches found"}
nums.find(arg) { |num| num == 5 }

> "No matches found"

Just a quick edit, you can return any value in the lambda or proc, whether it be raising an error or returning a value. I imagine raising an error and error handling is a common use though

Edit2: Removed link to an article explaining this method. Seems the blog post has been removed :(

like image 103
philip yoo Avatar answered Nov 15 '22 06:11

philip yoo