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 Y.
http://DevMentor.org
Do Good ~ Share Freely
Rajinder Y. wrote:
exit
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 Y.
http://DevMentor.org
Do Good ~ Share Freely
On 13.10.2009 01:47, Rajinder Y. wrote:
@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
Brian C. wrote:
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?
end
Comparable.instance_methods
=> [“==”, “>=”, “<”, “<=”, “>”, “between?”]
Regards,
Brian.
–
Kind Regards,
Rajinder Y.
http://DevMentor.org
Do Good ~ Share Freely
Rajinder Y. 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.
Rajinder Y. 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.
Robert K. wrote:
puts “”
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 Y.
http://DevMentor.org
Do Good ~ Share Freely
2009/10/14 Rajinder Y. [email protected]:
Enumerable module, and you can now add extra functionality which is specific
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