Ruby的find方法-参数是什么?

8

我正在进行一些探索。关于Ruby的

.find(ifnone = nil) { |obj| block } 
方法:从阅读文档中,我认为你可以传递一个作为参数的方法,当指定条件没有匹配时,该方法将被执行。

文档中说:

"如果指定了ifnone,则调用它并返回其结果;否则返回nil。"

这似乎适用于任何已经返回nil的方法,例如:

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

如果我使用一个会返回结果的方法,例如:

def message
 p 'No match.'
end

那么我会得到:

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

请问有人能够详细解释一下在这里传递给find方法的是什么类型的参数/方法吗?谢谢。

2个回答

8

很高兴你问这个问题。我之前从未考虑过find方法的这个参数,因为以前从未使用过它。我总是忽略它,直到你在这里提到它。

你将传递给可枚举对象(如find)的参数将是一个 lambda 表达式或 proc(过程)。如果未找到匹配项,则不会返回默认的 nil,而是返回 lambda/proc。

下面是一个快速的例子:

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

> ArgumentError: No matches found

同样的,您也可以传递一个Proc。
nums = [1, 2, 3, 4]
arg = Proc.new {"No matches found"}
nums.find(arg) { |num| num == 5 }

> "No matches found"

快速编辑一下,您可以在lambda或proc中返回任何值,无论是引发错误还是返回值。我想引发错误和错误处理是常见用途

编辑2:删除了解释这种方法的文章链接。似乎博客文章已被删除 :(


1
我也曾想忽略那个参数。很高兴我们都学到了东西!我记得一段时间前看过那篇相关的文章,但是找不到了。谢谢:D - Nathaniel Miller

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

这是一个重要提示。 find 需要一个可调用的对象,即能响应 #call 方法的对象。由于 Ruby 是鸭子类型,下列所有对象都可以:

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是构建另一种Proc对象的方式;不同的语法会产生略微不同的语义,但要点是lambda同样有效。)

接下来是一个反常的例子(已过时):

require 'continuation'
callcc do |notfound|
  ...find(notfound) { ... }
  ...
end

虽然这看起来很全面,但我理解得更少了。我认为我还不够先进,无法充分利用所有信息。 - Nathaniel Miller
1
哈哈,抱歉。从中要记住的主要内容是 - 它可以是具有“调用”方法的任何东西。这包括ProcMethod对象,它们的call方法执行它们包装的代码。 - Amadan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接