Why does 6.times.map work in ruby 1.8.7 but not 1.8.6
Asked Answered
I

4

7

The following code snippet works fine in 1.8.7 on Mac OS X, but not in 1.8.6 on Ubuntu. Why? Is there a workaround?

Works in 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"]
>>

But not in 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> 

Why is there a difference? What's the workaround for 1.8.6?

Intransigent answered 2/5, 2010 at 21:18 Comment(0)
T
17

In 1.8.7+ iterator methods like times return an enumerator if they are called without a block. In 1.8.6 you have to do

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

Or for this specific use case you could simply do (0...6).map {...}

Toil answered 2/5, 2010 at 21:27 Comment(1)
You can now require only the backports you need. In this case... require 'backports/1.8.7/integer/times'Design
K
6

In Ruby 1.9, the library was changed so functions that did iteration would return an Enumerator object if they were called without a block. A whole host of other language features were also changed, and it was widely known that compatibility would be broken between Ruby 1.8.x and Ruby 1.9 in the interests of improving the language as a whole. Most people didn't find this too distressing.

The Ruby development team decided that Ruby 1.8.7 should be a transition release adding some of the library features that Ruby 1.9 introduced. They took a lot of criticism for the decision, and many enterprise Ruby users remained (and many still remain) running Rails on Ruby 1.8.6, because they feel the changes introduced 1.8.7 are just too large, and too risky. But nevertheless, 1.8.7 remains, and having iteration functions return Enumerators is one of the features that was incorporated.

It is this migration feature that you're seeing in 1.8.7, which is not present in 1.8.6.

sepp2k's answer gives a good workaround. There's not much for me to add on that count.

Kunzite answered 2/5, 2010 at 21:46 Comment(1)
I'd add that 1.8.7 is mostly compatible (and when it isn't, 1.9 won't be). Check this question #2544685Design
F
1

Because 1.8.6 #times yields on the given block, while 1.8.7 returns an Enumerator object you can keep around and implements Enumerable.

Frontiersman answered 2/5, 2010 at 21:34 Comment(0)
T
1

Ruby 1.8.7 introduces many changes. If you want to use them in Ruby 1.8.6, simply

require 'backports'

That's it. This gives you many methods of 1.9.1 and the upcoming 1.9.2 as well, although it's possible to require 'backports/1.8.7' for just the changes of 1.8.7, or even just the backports you need, e.g. require 'backports/1.8.7/integer/times'

Trujillo answered 3/5, 2010 at 13:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.