Enumerating and mixin

I am trying to learn the correct way to enumerate in Ruby, a few things are missing in my 1st stab at this. How do I use mixin with Enumerable to rewrite the class I have below? I can't seem to find a concrete example online?

I know I am also missing code to override <=> if I wanted to do sorting, are the other overrides I am missing?

How do I make my code more elegant, Thanks!

class Vowels
    def initialize
       @index = 0
       @list = %w(a e i o u)
    end

    def each
       while( @index < @list.size )
          if @index >= @list.size
             yield nil
             exit
          else
             yield @list[@index]
             @index += 1
          end
       end
    end

    def first
       @index=0
    end
end

obj = Vowels.new

obj.each { |x| puts x }

···

--
Kind Regards,
Rajinder Yadav

http://DevMentor.org
Do Good ~ Share Freely

Rajinder Yadav wrote:

I am trying to learn the correct way to enumerate in Ruby, a few things are missing in my 1st stab at this. How do I use mixin with Enumerable to rewrite the class I have below? I can't seem to find a concrete example online?

I know I am also missing code to override <=> if I wanted to do sorting, are the other overrides I am missing?

How do I make my code more elegant, Thanks!

class Vowels
   def initialize
      @index = 0
      @list = %w(a e i o u)
   end

   def each
      while( @index < @list.size )
         if @index >= @list.size
            yield nil
            exit
         else
            yield @list[@index]
            @index += 1
         end
      end
   end

   def first
      @index=0
   end
end

obj = Vowels.new

obj.each { |x| puts x }

OK I managed to sweet the code down to the following, is there anything else I missed?

class Vowels
    include Enumerable
    def initialize
       @list = %w(u e a o i)
    end

    def each
       @list.each { |item| yield item }
    end
end

obj = Vowels.new

obj.each { |s| print s }
puts ""
obj.sort.each { |s| print s }
puts ""

···

--
Kind Regards,
Rajinder Yadav

http://DevMentor.org
Do Good ~ Share Freely

Rajinder Yadav wrote:

OK I managed to sweet the code down to the following, is there anything
else I
missed?

That's fine. So far your Vowels class doesn't really do anything more
than a simple Array would, but you've shown how your class gains methods
from the Enumerable module, and you can now add extra functionality
which is specific to a set of vowels. (This is composition by
delegation, an approach I highly recommend)

You mention <=>. This isn't needed here because each of the elements you
yield is a String, and strings already have <=> and so the elements can
be sorted. But if you want a different exercise, try:

class Vowel
  include Comparable
  def initialize(v)
    @v = v
  end
  def to_s
    @v
  end
  def <=>(other)
    @v <=> other.to_s
  end
end

v1 = Vowel.new("a")
v2 = Vowel.new("e")
v1 < v2 #=> true
v3 = Vowel.new("e")
v2 == v3 #=> true

Here you're exercising a different mixin, Comparable. It takes any class
which implements a <=> operator, and adds these methods for you:

Comparable.instance_methods

=> ["==", ">=", "<", "<=", ">", "between?"]

Regards,

Brian.

···

--
Posted via http://www.ruby-forum.com/\.

Two notes: you can actually pass the block directly on to method each of Array.

def each(&b)
   @list.each(&b)
end

And: conventionally #each returns self.

Taking both together you could do

def each(&b)
   @list.each(&b)
   self
end

Kind regards

  robert

···

On 13.10.2009 01:47, Rajinder Yadav wrote:

OK I managed to sweet the code down to the following, is there anything else I missed?

class Vowels
    include Enumerable
    def initialize
       @list = %w(u e a o i)
    end

    def each
       @list.each { |item| yield item }
    end
end

obj = Vowels.new

obj.each { |s| print s }
puts ""
obj.sort.each { |s| print s }
puts ""

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Brian Candler wrote:

Rajinder Yadav wrote:

OK I managed to sweet the code down to the following, is there anything else I
missed?

That's fine. So far your Vowels class doesn't really do anything more than a simple Array would, but you've shown how your class gains methods from the Enumerable module, and you can now add extra functionality which is specific to a set of vowels. (This is composition by delegation, an approach I highly recommend)

You mention <=>. This isn't needed here because each of the elements you yield is a String, and strings already have <=> and so the elements can be sorted. But if you want a different exercise, try:

Brian thanks for the demonstration of how to use Comparable, and also pointing out the other methods that can be redefined. If you didn't mention that, I would have stopped at <=>. Although I suspect the other methods make use of <=> internally?

···

class Vowel
  include Comparable
  def initialize(v)
    @v = v
  end
  def to_s
    @v
  end
  def <=>(other)
    @v <=> other.to_s
  end
end

v1 = Vowel.new("a")
v2 = Vowel.new("e")
v1 < v2 #=> true
v3 = Vowel.new("e")
v2 == v3 #=> true

Here you're exercising a different mixin, Comparable. It takes any class which implements a <=> operator, and adds these methods for you:

Comparable.instance_methods

=> ["==", ">=", "<", "<=", ">", "between?"]

Regards,

Brian.

--
Kind Regards,
Rajinder Yadav

http://DevMentor.org
Do Good ~ Share Freely

Robert Klemme wrote:

OK I managed to sweet the code down to the following, is there anything else I missed?

class Vowels
    include Enumerable
    def initialize
       @list = %w(u e a o i)
    end

    def each
       @list.each { |item| yield item }
    end
end

obj = Vowels.new

obj.each { |s| print s }
puts ""
obj.sort.each { |s| print s }
puts ""

Two notes: you can actually pass the block directly on to method each of Array.

def each(&b)
  @list.each(&b)
end

And: conventionally #each returns self.

Taking both together you could do

def each(&b)
  @list.each(&b)
  self
end

Robert, I didn't know method each should return self, learned something to add to my notes =), also seeing use of &b to denote a code-block drives home what I've been reading, thanks!

···

On 13.10.2009 01:47, Rajinder Yadav wrote:

Kind regards

    robert

--
Kind Regards,
Rajinder Yadav

http://DevMentor.org
Do Good ~ Share Freely

Brian Candler wrote:

Rajinder Yadav wrote:

OK I managed to sweet the code down to the following, is there anything
else I
missed?

That's fine. So far your Vowels class doesn't really do anything more than
a simple Array would, but you've shown how your class gains methods from the
Enumerable module, and you can now add extra functionality which is specific
to a set of vowels. (This is composition by delegation, an approach I highly
recommend)

You mention <=>. This isn't needed here because each of the elements you
yield is a String, and strings already have <=> and so the elements can be
sorted. But if you want a different exercise, try:

Brian thanks for the demonstration of how to use Comparable, and also
pointing out the other methods that can be redefined. If you didn't mention
that, I would have stopped at <=>. Although I suspect the other methods make
use of <=> internally?

Exactly - as Brian wrote. You can "see" this at work here:

09:45:55 ~$ ruby19 -e 'class X;include Comparable;def <=>(o);0
end;end;x=X.new;set_trace_func lambda {|*a| p a};x<x'
["c-return", "-e", 1, :set_trace_func, #<Binding:0x100a4bb8>, Kernel]
["line", "-e", 1, nil, #<Binding:0x100a4a78>, nil]
["c-call", "-e", 1, :<, #<Binding:0x100a499c>, Comparable]
["call", "-e", 1, :<=>, #<Binding:0x100a4898>, X]
["line", "-e", 1, :<=>, #<Binding:0x100a47a8>, X]
["return", "-e", 1, :<=>, #<Binding:0x100a46cc>, X]
["c-return", "-e", 1, :<, #<Binding:0x1001d744>, Comparable]
09:46:07 ~$

Here you're exercising a different mixin, Comparable. It takes any class
which implements a <=> operator, and adds these methods for you:

Comparable.instance_methods

=> ["==", ">=", "<", "<=", ">", "between?"]

Kind regards

robert

···

2009/10/14 Rajinder Yadav <devguy.ca@gmail.com>:

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Rajinder Yadav wrote:

Brian thanks for the demonstration of how to use Comparable, and also
pointing
out the other methods that can be redefined. If you didn't mention that,
I would
have stopped at <=>. Although I suspect the other methods make use of
<=>
internally?

That's exactly what Comparable does: these new methods in turn call the
<=> method that you defined.

In the same way, Enumerable gives you a whole bunch of new methods,
which in turn make use of 'each' (and only 'each'). So as long as you
have defined an 'each' method which yields the collection members in
turn, all the other methods in Enumerable will work.

Regards,

Brian.

···

--
Posted via http://www.ruby-forum.com/\.