7

以下代码片段在 Mac OS X 上的 1.8.7 中运行良好,但在 Ubuntu 上的 1.8.6 中运行良好。为什么?有解决方法吗?

适用于 1.8.7:

$ ruby --version
ruby 1.8.7 (2009-06-08 patchlevel 173) [universal-darwin10.0]
ltredgate15:eegl leem$ irb
>> 6.times.map {'foo'}
=> ["foo", "foo", "foo", "foo", "foo", "foo"]
>>

但不在 1.8.6 中:

# ruby --version
ruby 1.8.6 (2008-08-11 patchlevel 287) [i686-linux]
Ruby Enterprise Edition 20090610
# irb
irb(main):001:0> 6.times.map {'foo'}
LocalJumpError: no block given
        from (irb):1:in `times'
        from (irb):1
irb(main):002:0> 

为什么有区别?1.8.6 的解决方法是什么?

4

4 回答 4

17

在 1.8.7+ 迭代器方法times中,如果在没有块的情况下调用它们,则返回一个枚举器。在 1.8.6 你必须做

require 'enumerator'
6.enum_for(:times).map {...}

或者对于这个特定的用例,你可以简单地做 (0...6).map {...}

于 2010-05-02T21:27:14.877 回答
6

在 Ruby 1.9 中,该库已更改,因此如果在没有块的情况下调用它们,则执行迭代的函数将返回一个 Enumerator 对象。大量其他语言特性也发生了变化,众所周知,为了改进整个语言,Ruby 1.8.x 和 Ruby 1.9 之间的兼容性会被破坏。大多数人并不觉得这太令人痛苦。

Ruby 开发团队决定 Ruby 1.8.7 应该是一个过渡版本,添加了 Ruby 1.9 引入的一些库特性。他们对这个决定提出了很多批评,许多企业 Ruby 用户仍然(并且仍然很多)在 Ruby 1.8.6 上运行 Rails,因为他们觉得 1.8.7 引入的更改太大,而且风险太大。但是,1.8.7 仍然存在,并且让迭代函数返回 Enumerators 是合并的功能之一。

您在 1.8.7 中看到的正是这种迁移功能,而 1.8.6 中没有。

sepp2k 的回答提供了一个很好的解决方法。我没有太多要补充的。

于 2010-05-02T21:46:10.967 回答
1

因为 1.8.6 #times 在给定块上产生,而 1.8.7 返回一个 Enumerator 对象,您可以保留并实现 Enumerable。

于 2010-05-02T21:34:24.160 回答
1

Ruby 1.8.7 引入了许多变化。如果你想在 Ruby 1.8.6 中使用它们,只需

require 'backports'

就是这样。这为您提供了 1.9.1 和即将推出的 1.9.2 的许多方法,尽管可以require 'backports/1.8.7'仅针对 1.8.7 的更改,甚至只是您需要的反向移植,例如require 'backports/1.8.7/integer/times'

于 2010-05-03T13:57:51.933 回答