Yield example baffling - need help


#1

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 C., MS MA, LMHC - Private practice Psychotherapist
Bellingham, Washington, U.S.A: (360) 920-1226
<< removed_email_address@domain.invalid >> (email)
<< TomCloyd.com >> (website)
<< sleightmind.wordpress.com >> (mental health weblog)

#2

Tom C. wrote:

end
How can that yield do anything? How does it know about the block? It’s

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 C., MS MA, LMHC - Private practice Psychotherapist
Bellingham, Washington, U.S.A: (360) 920-1226
<< removed_email_address@domain.invalid >> (email)
<< TomCloyd.com >> (website)
<< sleightmind.wordpress.com >> (mental health weblog)

#3

Hi –

On Thu, 15 Jan 2009, Tom C. wrote:

end
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?

I don’t think it’s weird, and I’d encourage you not to feel glum about
having to accept it. It’s actually very elegant and cool.

The block, like the argument list, is a syntactic construct, part of
the method call. It is not, however, an argument; as you say, it is
not passed in (though you can “capture” it in a variable if needed).
It represents an anonymous function that is being made available for
execution, via yield, to the method.

When you say the method can’t possibly see the block, you’re assuming
that in a state of nature, methods can receive arguments but can’t see
code blocks :slight_smile: Of course none of it happens except because of how
it’s engineered, and the code block is part of the engineering, just
like the argument list.

David


David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.rubypal.com
Coming in 2009: The Well-Grounded Rubyist (http://manning.com/black2)

http://www.wishsight.com => Independent, social wishlist management!


#4

Hi –

On Thu, 15 Jan 2009, Tom C. wrote:

end

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 :slight_smile:

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 A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.rubypal.com
Coming in 2009: The Well-Grounded Rubyist (http://manning.com/black2)

http://www.wishsight.com => Independent, social wishlist management!


#5

Tom C. wrote:

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.


#6

David A. Black wrote:

iter = 0
I see a method with one parameter. There a block to the right of the
Or is it just a weird Ruby idiom I’ll just have to accept?

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 C., MS MA, LMHC - Private practice Psychotherapist
Bellingham, Washington, U.S.A: (360) 920-1226
<< removed_email_address@domain.invalid >> (email)
<< TomCloyd.com >> (website)
<< sleightmind.wordpress.com >> (mental health weblog)