【问题标题】:Ruby Enumerator - Why Finish with Exception?Ruby 枚举器 - 为什么以异常结束?
【发布时间】:2011-03-13 20:32:06
【问题描述】:

在 Ruby 中迭代一个块非常简单——它干净利落地完成并继续执行其余代码。

另一方面,使用枚举器进行迭代有点令人困惑。如果您在没有块的情况下调用 :each ,则会返回一个 Enumerator 。然后可以在 Enumerator 上调用 :next 以获取每个下一个迭代值。

然后是奇怪的部分——当迭代完成时,枚举器不是返回 nil,而是抛出一个异常:“迭代到达结束”。结果是它甚至没有返回值。

例如:

test = [ 'test_value' ]
enumerator = test.each
enumerator.next
>> "test_value"
enumerator.next
>> StopIteration: iteration reached at end

这样做的原因仅仅是因为枚举器可以返回 nil 值吗?答案只有在我发布此内容时才出现(所以我仍将发布它),但似乎必须如此。

如果是这样,这是处理此类问题的典型方式吗?使用异常来处理基本上按预期执行的代码似乎很奇怪。

【问题讨论】:

    标签: ruby exception enumerator


    【解决方案1】:

    您是正确的,原因是nil 可以由枚举器作为有效值返回。为了回答您关于这是否是典型的问题,Python 以同样的方式处理它,使用了一个也称为 StopIteration 的异常。

    >>> my_list = [1,2,3]
    >>> i = iter(my_list)
    >>> i.next()
    1
    >>> i.next()
    2
    >>> i.next()
    3
    >>> i.next()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    StopIteration
    

    当然,大多数时候 next 不会被直接调用(eachfor 循环被使用)所以这个底层机制不会经常暴露。

    【讨论】:

    • OCaml 更进一步 - 如果没有表示密钥,Ruby 的 hash[key] (List.assoc key hash) 或多或少等价物会引发异常 (Not_found)。这实际上是非常合乎逻辑的 - 当您调用 :next 时,您期望的“正常”事情是获得下一个值。 没有得到下一个值显然是一种例外情况。
    • @Amadan: hash.fetch(key) 将在未找到密钥时引发 KeyError
    • 有趣的论点 Amadan - 我买它。
    【解决方案2】:

    是的,nil 仍然是一个结果,这与没有返回值不同。这与尝试访问内存中不存在的变量或位置基本相同。这就是为什么你想要一个异常而不是返回一个 nil。听起来你想通了:-)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-02-04
      • 2018-10-25
      • 2016-11-26
      • 1970-01-01
      • 1970-01-01
      • 2019-06-21
      • 1970-01-01
      相关资源
      最近更新 更多