为什么6.times.map在ruby 1.8.7中工作,而不是1.8.6

时间:2010-05-02 21:18:36

标签: ruby ruby-enterprise-edition

以下代码段在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 个答案:

答案 0 :(得分:16)

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

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

或者对于此特定用例,您只需执行(0...6).map {...}

即可

答案 1 :(得分: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仍然存在,并且具有迭代函数返回枚举器是已合并的功能之一。

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

sepp2k的回答给出了一个很好的解决方法。我没有太多可以补充这一点。

答案 2 :(得分:1)

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

答案 3 :(得分:1)

Ruby 1.8.7引入了many changes。如果你想在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'