计算一个方法可以被调用的次数,直到它返回nil为止



背景:我需要确定远程位置的记录数量。记录按顺序编号(从0开始,没有间隙),并且只能根据它们的编号逐个提取。

通过网络获取记录的方法在成功时返回truthy值,在失败时返回false。以下是一个例子:

fetch_record(0) #=> true (record #0 exists)
fetch_record(1) #=> true (record #1 exists)
fetch_record(2) #=> true (record #2 exists)
fetch_record(3) #=> nil  (no record #3)

我正试图找到一种优雅的方法来计算我可以用递增参数调用fetch_record的次数,直到它返回nil(在上例中为3次)。

到目前为止我尝试了什么

考虑到这种简化的测试实现:

def fetch_record(index)
  raise if index > 3 # just to prevent endless loops
  true if index < 3
end

以下是我的尝试:

  1. 带有显式计数器变量的while循环显然可以工作,但我看起来不太习惯:

    i = 0
    i += 1 while fetch_record(i)
    i
    #=> 3
    
  2. 我可以使用带有显式结果值的stepbreak,但这看起来很麻烦:

    0.step(by: 1).each { |i| break i unless fetch_record(i) }
    #=> 3
    
  3. 懒惰的枚举器更糟糕:

    0.step(by: 1).lazy.map { |i| fetch_record(i) }.take_while(&:itself).count
    #=> 3
    

有没有一种更容易的方法来实现上述目标?

假设您可以自由地以另一种方式实现fetch_record,则为不存在的记录返回true

def fetch_record index
  index >= 3
end
(0..Float::INFINITY).detect &method(:fetch_record)
#⇒ 3

take_while any?

records = 0.step.take_while{|i| fetch_record(i)}

最新更新