yield example baffling - need help

T

Tom Cloyd

I'm studying the yield statement for the first time, today.

All's well until I see this example:

def myeach(myarray)
iter = 0
while (iter < myarray.length):
yield(myarray[iter])
iter += 1
end
end

testarray = [1,2,3,4,5]
myeach(testarray) {|item| print "#{item}:"}
→ 1:2:3:4:5:

I see a method with one parameter. There a block to the right of the
method call, inexplicably. It would make sense if some iteration were
going on, but I don't see that at all. One call, one execution (with a
loop), and we're out. What does "item" have to count through?

How can that yield do anything? How does it know about the block? It's
not passed in. The iteration appears to be happening IN the method,
using a block it cannot possibly see. Ouch! After some minutes, I'm not
getting this at all.

Can anyone clear my head for me. I've never seen anything like this. Or
is it just a weird Ruby idiom I'll just have to accept?

Thanks in advance.

Tom


--

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Tom Cloyd, MS MA, LMHC - Private practice Psychotherapist
Bellingham, Washington, U.S.A: (360) 920-1226
<< (e-mail address removed) >> (email)
<< TomCloyd.com >> (website)
<< sleightmind.wordpress.com >> (mental health weblog)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
T

Tom Cloyd

Tom said:
I'm studying the yield statement for the first time, today.

All's well until I see this example:

def myeach(myarray)
iter = 0
while (iter < myarray.length):
yield(myarray[iter])
iter += 1
end
end

testarray = [1,2,3,4,5]
myeach(testarray) {|item| print "#{item}:"}
→ 1:2:3:4:5:

I see a method with one parameter. There a block to the right of the
method call, inexplicably. It would make sense if some iteration were
going on, but I don't see that at all. One call, one execution (with a
loop), and we're out. What does "item" have to count through?

How can that yield do anything? How does it know about the block? It's
not passed in. The iteration appears to be happening IN the method,
using a block it cannot possibly see. Ouch! After some minutes, I'm
not getting this at all.

Can anyone clear my head for me. I've never seen anything like this.
Or is it just a weird Ruby idiom I'll just have to accept?

Thanks in advance.

Tom
Arrgh. What a dolt. I just realized that ALL the yield examples I've
been studying have this block sitting over to the right - I was
converting the curly braces to parens in my mind, and so didn't see
them. It IS idiomatic weirdness. I yield to higher wisdom.

t.

--

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Tom Cloyd, MS MA, LMHC - Private practice Psychotherapist
Bellingham, Washington, U.S.A: (360) 920-1226
<< (e-mail address removed) >> (email)
<< TomCloyd.com >> (website)
<< sleightmind.wordpress.com >> (mental health weblog)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
T

Tom Cloyd

David said:
Hi --

Tom said:
I'm studying the yield statement for the first time, today.

All's well until I see this example:

def myeach(myarray)
iter = 0
while (iter < myarray.length):
yield(myarray[iter])
iter += 1
end
end

testarray = [1,2,3,4,5]
myeach(testarray) {|item| print "#{item}:"}
→ 1:2:3:4:5:

I see a method with one parameter. There a block to the right of the
method call, inexplicably. It would make sense if some iteration
were going on, but I don't see that at all. One call, one execution
(with a loop), and we're out. What does "item" have to count through?

How can that yield do anything? How does it know about the block?
It's not passed in. The iteration appears to be happening IN the
method, using a block it cannot possibly see. Ouch! After some
minutes, I'm not getting this at all.

Can anyone clear my head for me. I've never seen anything like this.
Or is it just a weird Ruby idiom I'll just have to accept?

Thanks in advance.

Tom
Arrgh. What a dolt. I just realized that ALL the yield examples I've
been studying have this block sitting over to the right - I was
converting the curly braces to parens in my mind, and so didn't see
them. It IS idiomatic weirdness. I yield to higher wisdom.

Half the fun, actually, is that while you know what you're yielding,
you never know exactly what you're yielding *to* :)

The block construct actually has two common use patterns: iterating
through collections, and yielding "magic pen" objects.[1] An example
of the magic pen is File.open:

File.open("blah", "w") do |fh|
fh.puts(whatever)
end

where the open method, which you never have to see, does the
housekeeping, including closing the file for you. You just get the
magic pen (the file handle). That pattern is, I think, particularly
nice.


David

[1] http://dablog.rubypal.com/2007/2/18/the-magic-pens-of-ruby
David - very nice! Plus, you made me howl with laughter. Yes, I often
cannot see to what I am yielding. And of course, we spend a lifetime
approaching the Great Yield. Um...but not tonight, I think!

Thanks for your eloquence.

t.

--

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Tom Cloyd, MS MA, LMHC - Private practice Psychotherapist
Bellingham, Washington, U.S.A: (360) 920-1226
<< (e-mail address removed) >> (email)
<< TomCloyd.com >> (website)
<< sleightmind.wordpress.com >> (mental health weblog)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
B

Brian Candler

Tom said:
How can that yield do anything? How does it know about the block? It's
not passed in. The iteration appears to be happening IN the method,
using a block it cannot possibly see. Ouch! After some minutes, I'm not
getting this at all.

Maybe it's clearer if you rewrite myeach to show explicitly the block
being passed in, and being called.

def myeach(myarray, &block) # <<<
iter = 0
while (iter < myarray.length):
block.call(myarray[iter]) # <<<
iter += 1
end
end

Even if there is no &foo in the argument list, you can still pass a
block when you call the method. The method can call it anonymously using
'yield', and test for its presence using 'block_given?' (*)

BTW, Proc#[] is an alias for Proc#call, so this gives you three choices:

block.call(args) # only if block captured into a variable
block[args] # ditto
yield args

HTH,

Brian.

(*) It's occasionally a source of head-scratching when you pass a block
to a method which doesn't expect one, and so it's silently ignored. Ruby
can't and doesn't warn you of this.
 

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

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top