Infinite Lists

Infinite lists (also known as lazy streams) provide a way to represent arbitrary sequences that can be traversed by applying a certain function that gets to you the next element for any given element in the list. For example, if we start with any even number, we can get to the next one in the sequence by simply adding 2 to our original element.

Before we look at more complicated examples, let’s take a look at how we can represent the even sequence of numbers this way, using a simple Ruby object:

module EvenSeries
  class Node
    def initialize(number=0)
      @value = number
      @next  = lambda { Node.new(number + 2) }
    end

    attr_reader :value

    def next
      @next.call
    end
  end
end

e = EvenSeries::Node.new(30)
10.times do
  p e.value
  e = e.next
end

When we run this code, we get the following output:

30
32
34
36
38
40
42
44
46
48

The implementation should be mostly self-explanatory. An EvenSeries::Node is nothing more than a number and a Proc that is designed to add 2 to that number and construct a new Node. What we end up with is something that looks similar to a linked list, and we can clearly see what happens when we take 10 steps forward from 30 through the even numbers.

The key innovation is that we’ve turned an external iteration and state transformation into an internal one. The benefits of this technique will become more clear in later examples, but for now, it’s worth noting that this is the key motivation for creating such a construct.

Although this example shows you the simplest thing that ...

Get Ruby Best Practices now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.