The Artima Developer Community
Sponsored Link

Ruby Buzz Forum
Ruby: Enumerators and Generators

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Andrew Johnson

Posts: 39
Nickname: jandrew
Registered: Mar, 2004

Simple things ...
Ruby: Enumerators and Generators Posted: May 17, 2004 2:06 PM
Reply to this message Reply

This post originated from an RSS feed registered with Ruby Buzz by Andrew Johnson.
Original Post: Ruby: Enumerators and Generators
Feed Title: Simple things ...
Feed URL: http://www.siaris.net/index.cgi/index.rss
Feed Description: On programming, problem solving, and communication.
Latest Ruby Buzz Posts
Latest Ruby Buzz Posts by Andrew Johnson
Latest Posts From Simple things ...

Advertisement
byline: Andrew L Johnson

Included with the Ruby distribution are the generator library and the enumerator extension — both useful tools when ordinary iteration doesn’t quite measure up.

The enumerator extension is simple in concept: create a new Enumerable object given an object and a method of that object to be used as an iterator. For example, if we add an each_even iterator to the Array class to iterate over every element with an even numbered index, we can use enumerator to create enumerable versions of an array object that use each_even as the iterator:

  require 'enumerator'

  class Array
    def each_even
      self.each_with_index do|el,i|
        yield el if i % 2 == 0
      end
    end
  end

  arr = ['a','b','c','d','e','f','g','h']
  enum = Enumerable::Enumerator.new(arr, :each_even)
  ev = enum.map {|x| x + x}
  p ev                      #=> ["aa", "cc", "ee", "gg"]

In addition to the constructor above, the following convenience functions are added to the Object class:

  to_enum(:iter, *args)
  enum_for(:iter, *args)

The Enumerable module is also extended with five additional methods:

  each_slice(n)    # iterates over non-overlapping chunks of size n
  enum_slice(n)    # new enumerator object using :each_slice(n)

    ('a'..'m').each_slice(4) {|sl| p sl}
    #  produces:
      ["a", "b", "c", "d"]
      ["e", "f", "g", "h"]
      ["i", "j", "k", "l"]
      ["m"]

  each_cons(n)     # iterates over successive chunks of size n
  enum_cons(n)     # new enumerator using :each_cons(n)

    ('a'..'m').each_cons(4) {|sl| p sl}
    # produces:
      ["a", "b", "c", "d"]
      ["b", "c", "d", "e"]
      ["c", "d", "e", "f"]
      ["d", "e", "f", "g"]
      ["e", "f", "g", "h"]
      ["f", "g", "h", "i"]
      ["g", "h", "i", "j"]
      ["h", "i", "j", "k"]
      ["i", "j", "k", "l"]
      ["j", "k", "l", "m"]

  enum_with_index  # new enumerator using :each_with_index

The generator library generates external iterators from either blocks or Enumerable objects (in the latter case, the :each iterator is externalized).

require 'generator' arr = ('a' .. 'm') gen = Generator.new(arr) while gen.next? p gen.next end

This makes iterating over multiple objects relatively easy. However, the generator library also provides the SyncEnumerator class which makes multiple iteration a breeze:

  require 'generator'

  a = (4..5)
  b = ['a',nil,'c']
  c = ['x','y','x']

  enum = SyncEnumerator.new(a, b, c)
  enum.each {|row| p row}

  puts '---'
  table = [ [1,2,3], [4,5,6], [7,8,9] ]
  cols = SyncEnumerator.new(*table)
  cols.each {|col| p col}

  # produces:

    [4, "a", "x"]
    [5, nil, "y"]
    [nil, "c", "x"]
    ---
    [1, 4, 7]
    [2, 5, 8]
    [3, 6, 9]

All of which just goes to show: There’s more than one way to iterate an enumerable.

Discuss

__END__

Read: Ruby: Enumerators and Generators

Topic: Ruby Module Spotlight: Instiki -- There is no step three. Previous Topic   Next Topic Topic: Instiki 0.3.1: Before the Storm

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use