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.
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}!"
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.
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.
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 :(
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