Range Over Iterators in Ruby

Our example program demonstrates iteration over custom data structures and an infinite sequence generator. Here’s the full source code translated to Ruby.

Example

We start by defining the List class, which uses a linked list structure to hold elements.

class Element
  attr_accessor :next, :val

  def initialize(val)
    @val = val
    @next = nil
  end
end

class List
  def initialize
    @head = nil
    @tail = nil
  end

  def push(val)
    if @tail.nil?
      @head = Element.new(val)
      @tail = @head
    else
      @tail.next = Element.new(val)
      @tail = @tail.next
    end
  end

  def all
    Enumerator.new do |yielder|
      e = @head
      while e
        yielder << e.val
        e = e.next
      end
    end
  end
end

Pushing elements into the list

Method push adds an element to the list, handling both the empty and non-empty cases.

list = List.new
list.push(10)
list.push(13)
list.push(23)

Iterating over the list

We can iterate over the list using Ruby’s Enumerator.

list.all.each do |e|
  puts e
end

Collecting all elements

Ruby has built-in methods like to_a to collect values from an Enumerator.

all_elements = list.all.to_a
puts "all: #{all_elements.inspect}"

Infinite sequence generator

Next, we define a generator for Fibonacci numbers. The fib_gen method yields Fibonacci numbers indefinitely.

def fib_gen
  Enumerator.new do |yielder|
    a, b = 1, 1
    loop do
      yielder << a
      a, b = b, a + b
    end
  end
end

Using the Fibonacci generator

We can iterate over our Fibonacci generator and break under conditions we define.

fib_gen.each do |n|
  break if n >= 10
  puts n
end

Output of running the code

10
13
23
all: [10, 13, 23]
1
1
2
3
5
8

In summary, we translated the example to Ruby, focusing on idiomatic use of classes, methods, and Ruby’s powerful enumerator-based iteration. This translation demonstrates handling of both finite and infinite sequences elegantly.