Почему 6.times.map работает в ruby ​​1.8.7, а не 1.8.6 - PullRequest
7 голосов
/ 03 мая 2010

Следующий фрагмент кода отлично работает в 1.8.7 на Mac OS X, но не в 1.8.6 на Ubuntu Зачем? Есть ли обходной путь?

Работает в 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 ]

16 голосов
/ 03 мая 2010

В 1.8.7+ итерационных методах, таких как times, возвращаются перечислители, если они вызываются без блока. В 1.8.6 нужно сделать

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

Или для этого конкретного случая использования вы можете просто сделать (0...6).map {...}

6 голосов
/ 03 мая 2010

В Ruby 1.9 библиотека была изменена таким образом, чтобы функции, выполняющие итерацию, возвращали объект Enumerator, если они вызывались без блока. Также был изменен целый ряд других языковых функций, и было широко известно, что совместимость будет нарушена между Ruby 1.8.x и Ruby 1.9 в интересах улучшения языка в целом. Большинство людей не находили это слишком огорчительным.

Команда разработчиков Ruby решила, что Ruby 1.8.7 должен быть переходной версией, добавляющей некоторые функции библиотеки, представленные в Ruby 1.9. Они приняли много критики за это решение, и многие корпоративные пользователи Ruby продолжали (и многие все еще продолжают) запускать Rails на Ruby 1.8.6, потому что считают, что внесенные в 1.8.7 изменения слишком велики и слишком рискованны. Но, тем не менее, 1.8.7 остается, и наличие итерационных функций, возвращающих перечислители, является одной из функций, которые были включены.

Именно эту функцию миграции вы видите в 1.8.7, которой нет в 1.8.6.

Ответ sepp2k дает хороший обходной путь. Мне нечего добавить к этому счету.

1 голос
/ 03 мая 2010

В Ruby 1.8.7 внесено много изменений . Если вы хотите использовать их в Ruby 1.8.6, просто

require 'backports'

Вот и все. Это дает вам множество методов 1.9.1 и предстоящего 1.9.2, хотя возможно require 'backports/1.8.7' только для изменений 1.8.7 или даже для всего, что вам нужно, например, backports. require 'backports/1.8.7/integer/times'

1 голос
/ 03 мая 2010

Потому что 1.8.6 # раза дает в данном блоке, в то время как 1.8.7 возвращает объект Enumerator, который вы можете сохранить, и реализует Enumerable.

...