couple of pages looking at one of Ruby's neatest features: iterators.
So, our next problem with
SongList
is to implement the code in
method
[]
that takes a string and searches for a song with
that title. This seems straightforward: we have an array of songs, so
we just go through it one element at a time, looking for a match.
class SongList
def [](key)
if key.kind_of?(Integer)
return @songs[key]
else
for i in [email protected]
return @songs[i] if key == @songs[i].name
end
end
return nil
end
end
|
This works, and it looks comfortingly familiar: a
for
loop
iterating over an array. What could be more natural?
It turns out there
is something more natural. In a way,
our
for
loop is somewhat too intimate with the array; it asks for
a length, then retrieves values in turn until it finds a match. Why
not just ask the array to apply a test to each of its members?
That's just what the
find
method in
Array
does.
class SongList
def [](key)
if key.kind_of?(Integer)
result = @songs[key]
else
result = @songs.find { |aSong| key == aSong.name }
end
return result
end
end
|
We could use
if
as a statement modifier to shorten the
code even more.
class SongList
def [](key)
return @songs[key] if key.kind_of?(Integer)
return @songs.find { |aSong| aSong.name == key }
end
end
|
The method
find
is an iterator---a method that invokes a
block of code repeatedly. Iterators and code blocks are among the
more interesting features of Ruby, so let's spend a while looking into
them (and in the process we'll find out exactly what that line of code
in our
[]
method actually does).