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 0...@songs.length
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).