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:
No match.
=>nil
No match. =>nil
If I use a method that does return something, say:
\ndef message \n p 'No match.' \nend \n
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.
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 :(
NoMethodError: undefined method `call' for "No match.":String
This is a big hint. find
wants a callable object - ie something that responds to #call
. Since Ruby is duck-typed, all of these will work:
def message_method
puts "yo"
end
...find(method(:message_method)) { ... }
module MessageModule
def self.call
puts "yo"
end
end
...find(MessageModule) { ... }
class MessageClass
def call
puts "yo"
end
end
...find(MessageClass.new) { ... }
message_proc = Proc.new { puts "yo" }
...find(message_proc) { ... }
( lambda
is another way of constructing a Proc
object; the different syntax makes for a bit different semantics, but the point is lambda
would work just as well.)
And a perverse example (obsolete):
require 'continuation'
callcc do |notfound|
...find(notfound) { ... }
...
end
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.