Explaination of a bit of code

Hey, another question. This is kinda putting several concepts together
that i understand but the code is throwing me for some reason:

class Periods
def each
yield “Classical”
yield “Jazz”
yield “Rock”
end
end

periods = Periods.new
for genre in periods
print genre, " "
end

produces:
Classical Jazz Rock

So a simple for…in loop which is the same as using the .each for an
array/Hash, etc.

I guess I am having trouble thinking how this would work out. Each is
suppose to go through a set of items. however, where are the items? I
see three strings but they are used in yield statements. How is this
method actually working?

Dave L. wrote:

Each is suppose to go through a set of items.

each is supposed to whatever it has been defined to do. It’s not
special.
It’s not different from any other method. You can define it to do
whatever you
want. And in this case it is defined to yield three strings so that’s
what it
does.

And while we are at little samples of code…

if false
a = 1
end
3.times {|i| a = i }

a --> 2

I was looking at an example and was a bit confused why variable a got 2.
I undrestand the basic idea of this example (as long as a is defined
somewhere, evne if it’s value is never reached, it exists), but why 2?
Is the times method going from 0 to X-1 where X is the number in
X.times?

Dave L. wrote:

Is the times method going from 0 to X-1 where X is the number in
X.times?

Yes.
Try this: 3.times {|i| p i}
Prints:
0
1
2

HTH,
Sebastian

Dave L. wrote:

I guess I am having trouble thinking how this would work out. Each is
suppose to go through a set of items. however, where are the items? I
see three strings but they are used in yield statements. How is this
method actually working?

The method each is working just as you programme it. For Arrays (and
Enumerables, in general) it calls the passed block with each element of
the object (self) in turn, so in some useless pseudocode, Array#each
works like this:
for each element of self in e
yield(e)
end
Now you can see that your own each works just like
[“Classical”,“Jazz”,“Rock”].each{|e| yield(e)}
So, your Periods::new works like the array [“Classical”,“Jazz”,“Rock”]
itself. Only your object is a dummy array - it does not read the
elements from any kind of set or anything, it is just hardcoded to call
yield with these three strings. But from outside you cannot tell your
Period::new from [“Classical”,“Jazz”,“Rock”], they just behave in the
same way when we call the method each on them. And that’s why the for
loop sees your object as if it was the array of the three strings.

TPR.

Thanks all.

I should note that these are not my programs but snippets from a book
(Programming Guide to Ruby) that I am trying to make sure I understand.

Here’s another snippet I am wondering on:

catch (:done) do
while line = gets
throw :done unless fields = line.split(/\t/)
songlist.add(Song.new(*fields))
end
songlist.play
end

So, according to the book, it’s looking for badly formatted strings. If
there is a badly formatted string, the throw clause is invoked. Now,
the question is, where does the throw clause go. I see that catch
(:done) is right there, but how does the throw clause “find” the catch
clause.

In other words, I am trying to understand howt his works compared to…

while line = gets
throw :done unless fields = line.split (/\t/)
songlist.add(Song.new(*fields))
end
end

catch :done
#handle issues
end

Dave L. wrote:

Here’s another snippet I am wondering on:

catch (:done) do
while line = gets
throw :done unless fields = line.split(/\t/)
songlist.add(Song.new(*fields))
end
songlist.play
end

So, according to the book, it’s looking for badly formatted strings. If
there is a badly formatted string, the throw clause is invoked. Now,
the question is, where does the throw clause go.

The throw has to be inside a corresponding catch block, and it drops
you to the end of the catch block.

You can also give a value alongside the throw; if so, this is the value
“returned” by the catch block itself.

ans = catch(:hello) do
throw :hello, 2
puts “Never reached”
3
end
p ans # 2

I see that catch
(:done) is right there, but how does the throw clause “find” the catch
clause.

It’s pretty much the same as an exception. The interpreter winds back
the stack looking for a matching ‘catch’ block.

In other words, I am trying to understand howt his works compared to…

while line = gets
throw :done unless fields = line.split (/\t/)
songlist.add(Song.new(*fields))
end
end

catch :done
#handle issues
end

That won’t work, because when the throw executes, there is no enclosing
matching catch block.