Enumerating and mixin.

R

Rajinder Yadav

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
 
R

Rajinder Yadav

Rajinder said:
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
 
B

Brian Candler

Rajinder said:
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
=> ["==", ">=", "<", "<=", ">", "between?"]

Regards,

Brian.
 
R

Robert Klemme

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

Kind regards

robert
 
R

Rajinder Yadav

Brian said:
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
=> ["==", ">=", "<", "<=", ">", "between?"]

Regards,

Brian.


--
Kind Regards,
Rajinder Yadav

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

Rajinder Yadav

Robert said:
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!
Kind regards

robert


--
Kind Regards,
Rajinder Yadav

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

Robert Klemme

2009/10/14 Rajinder Yadav said:
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]
Comparable] said:
Here you're exercising a different mixin, Comparable. It takes any class
which implements a said:
Comparable.instance_methods

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

Kind regards

robert
 
B

Brian Candler

Rajinder said:
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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top