wtf?! Infinite Ranges in Ruby

First let’s define an Infinity constant (since Ruby does not come with one):

Inf = 1.0 / 0.0

Now let’s see if we can create a Range Object with it:

(1..Inf)

Okay, no errors. Now let’s try to use it:

(1..Inf).include?(10000000) #=> true
(1..Inf).include?(-10) #=> false
(-Inf..0).include?(-1000) #=> true
(-Inf..Inf).include?(-1000.456) #=> true

Now let’s try using it as a ‘lazy’ list:

(1..Inf).each.take(5) #=> [1, 2, 3, 4, 5]
(1..Inf).each.take(5).select { |v| v.even? } #=> [2, 4]
(100..Inf).step(100).take(3) #=> [100, 200, 300]

One last thing:

(1..Inf).each { |v| puts v }

output:
1
2
3
4
5
...etc (quite alot of numbers...)

Applications

lazy evaluation?

Some of the applications of Lazy Enumerators (discussed here: http://www.michaelharrison.ws/weblog/?p=163) can be accomplished using Infinite Ranges instead.

In particular, the lazy_select, and lazy_map family of functions defined in that article will also work fine with Infinite Ranges:

module Enumerable
  def lazy_select
    Enumerator.new do |yielder|
      each do |obj|
        yielder.yield(obj) if yield(obj)
      end
    end
  end
end

# first 4 even numbers
(1..Inf).lazy_select { |v| v.even? }.take(4)

output:  
[2, 4, 6, 8]

Credits

This trick was discovered by Beoran in response to a question by FreakGuard in #ruby-lang on freenode.

lazy_select by gfarfl.

EDIT: Okay, this trick isn’t 100% new, see here: http://weblog.jamisbuck.org/2007/2/7/infinity

About these ads

7 Responses to “wtf?! Infinite Ranges in Ruby”

  1. You can also do the following:

    Infinity = 1/0.0
    range = -Infinity..Infinity

    range.include?(-999244) => true
    range.include?(0) => true
    etc

    More info here: http://weblog.jamisbuck.org/2007/2/7/infinity

  2. I wonder what happens if you (1..Inf).to_a ? I’ll try it in irb and get back to you when it’s finished…

Trackbacks

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: