Forum: Ruby yield example baffling - need help

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Tom C. (Guest)
on 2009-01-15 03:41
(Received via mailing list)
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)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Tom C. (Guest)
on 2009-01-15 03:46
(Received via mailing list)
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)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
David A. Black (Guest)
on 2009-01-15 03:51
(Received via mailing list)
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 :-) 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!
David A. Black (Guest)
on 2009-01-15 03:56
(Received via mailing list)
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* :-)

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!
Tom C. (Guest)
on 2009-01-15 04:02
(Received via mailing list)
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)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Brian C. (Guest)
on 2009-01-16 15:23
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.
This topic is locked and can not be replied to.