Enumerable

Discussion in 'Ruby' started by Michael Saltzman, Aug 1, 2006.

  1. Am new to Ruby and have the folloiwng Question.

    I have a class, say Collect, and I want to mixin Enumerable. How do I
    write the each method in Collect?

    class Collect
    include Enumerable
    def initialize()
    @array = Array.new(0)
    @ct = 0
    end
    def add(item)
    @array.push(item)
    @ct += 1
    end
    def howmany
    @ct
    end
    def each
    #
    # Not sure how to do this????
    #
    end
    end

    --
    Posted via http://www.ruby-forum.com/.
    Michael Saltzman, Aug 1, 2006
    #1
    1. Advertising

  2. On 8/1/06, Michael Saltzman <> wrote:
    > Am new to Ruby and have the folloiwng Question.
    >
    > I have a class, say Collect, and I want to mixin Enumerable. How do I
    > write the each method in Collect?
    >
    > class Collect
    > include Enumerable
    > def initialize()
    > @array = Array.new(0)
    > @ct = 0
    > end
    > def add(item)
    > @array.push(item)
    > @ct += 1
    > end
    > def howmany
    > @ct
    > end
    > def each
    > #
    > # Not sure how to do this????
    > #
    > end
    > end


    Assuming you want to iterate over @array,

    def each
    @array.each {|i| yield i}
    end

    martin
    Martin DeMello, Aug 1, 2006
    #2
    1. Advertising

  3. On Tuesday 01 August 2006 16:43, Michael Saltzman wrote:
    > Am new to Ruby and have the folloiwng Question.
    >
    > I have a class, say Collect, and I want to mixin Enumerable. How do I
    > write the each method in Collect?
    >
    > class Collect
    > include Enumerable
    > def initialize()
    > @array = Array.new(0)
    > @ct = 0
    > end
    > def add(item)
    > @array.push(item)
    > @ct += 1
    > end
    > def howmany
    > @ct
    > end
    > def each
    > #
    > # Not sure how to do this????
    > #
    > end
    > end

    It depends what you want each to do? Just to wrap @array.each? In that case,
    this would work:
    def each
    @array.each {|item| yield item}
    end

    Of course you can do whatever you want to the array item in the block before
    you yield it again.

    An alternative technique is as follows:
    def each(&block)
    @array.each(&block)
    end

    I'm sure someone will correct me if I describe this slightly wonky, but the
    basic idea is that the interpreter converts the block argument to a proc with
    a name (I think I read an article that claimed a block is always converted to
    a proc, but when no &arg is given, it is simply a proc with no name,
    accessible of course via yield). This is then passed on to @array.each as a
    block argument.

    I don't know whether there are any real advantages or disadvantages to either
    method. Hope this helps

    Alex
    A. S. Bradbury, Aug 1, 2006
    #3
  4. Michael Saltzman wrote:
    > Am new to Ruby and have the folloiwng Question.
    >
    > I have a class, say Collect, and I want to mixin Enumerable. How do I
    > write the each method in Collect?
    >
    > class Collect
    > include Enumerable
    > def initialize()
    > @array = Array.new(0)
    > @ct = 0
    > end
    > def add(item)
    > @array.push(item)
    > @ct += 1
    > end
    > def howmany
    > @ct
    > end
    > def each
    > #
    > # Not sure how to do this????
    > #
    > end
    > end
    >


    You have several options:

    class Collect
    include Enumerable

    def initialize()
    @array = []
    end

    def add(item)
    @array.push(item)
    self
    end

    alias :<< :add

    def howmany
    @array.size
    end

    # option 1: use yield
    def each_1
    @array.each {|x| yield x}
    self
    end

    # option 2: delegate to Array's each
    def each_2(&b)
    @array.each(&b)
    self
    end
    end

    Kind regards

    robert
    Robert Klemme, Aug 1, 2006
    #4
  5. On Tuesday 01 August 2006 17:06, A. S. Bradbury wrote:
    > It depends what you want each to do? Just to wrap @array.each? In that
    > case, this would work:
    > def each
    > @array.each {|item| yield item}
    > end
    >
    > Of course you can do whatever you want to the array item in the block
    > before you yield it again.
    >
    > An alternative technique is as follows:
    > def each(&block)
    > @array.each(&block)
    > end
    >

    <snip>
    > I don't know whether there are any real advantages or disadvantages to
    > either method. Hope this helps


    Just did a quick benchmark out of curiosity:
    user system total real
    Two yields 15.720000 2.220000 17.940000 ( 20.336562)
    Pass the named block 4.130000 1.020000 5.150000 ( 5.562950)
    Direct on attr_accessor 3.810000 1.010000 4.820000 ( 5.440259)

    I passed the block {|i| i} and initialized @array to (1..100).to_a, and ran
    through 50000 times.

    Alex
    A. S. Bradbury, Aug 1, 2006
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jason Creighton

    Why isn't Enumerable in StringIO?

    Jason Creighton, Jul 25, 2003, in forum: Ruby
    Replies:
    1
    Views:
    100
  2. Pierre-Charles David

    Support for arbitrary iterators in Enumerable?

    Pierre-Charles David, Oct 2, 2003, in forum: Ruby
    Replies:
    2
    Views:
    128
  3. Nathaniel Talbott

    Enumerable#inject is surprising me...

    Nathaniel Talbott, Oct 7, 2003, in forum: Ruby
    Replies:
    0
    Views:
    87
    Nathaniel Talbott
    Oct 7, 2003
  4. Harry Ohlsen

    An addition to Array (or Enumerable)?

    Harry Ohlsen, Dec 28, 2003, in forum: Ruby
    Replies:
    11
    Views:
    176
    Dave Thomas
    Dec 29, 2003
  5. Daniel Sheppard
    Replies:
    0
    Views:
    103
    Daniel Sheppard
    Sep 16, 2005
Loading...

Share This Page