Writing a method to handle a code block?

From Beginning Ruby:

def each_vowel(&code_block)
  %w{a e i o u}.each { |vowel| code_block.call(vowel) }
end
each_vowel { |vowel| puts vowel }

I am trying to figure out how that works but I'm still having a bit of
trouble. Could someone break it down bit by bit to show what it's doing?

def each_vowel(&code_block)

It defines a method that takes a code block (is the & necessary?). What does
it mean to have a method that takes a code block?

  %w{a e i o u}.each { |vowel| code_block.call(vowel) }

Then it takes an array of vowels, which call the each method to pass each
one into the following block through |vowel| as a block argument. The block
arguments are then called by the variable code_block (I don't understand
this).

Brian

From Beginning Ruby:

def each_vowel(&code_block)
%w{a e i o u}.each { |vowel| code_block.call(vowel) }
end
each_vowel { |vowel| puts vowel }

I am trying to figure out how that works but I'm still having a bit of
trouble. Could someone break it down bit by bit to show what it's doing?

def each_vowel(&code_block)

It defines a method that takes a code block (is the & necessary?).

Yes the & is necessary, otherwise when you try to call this method
with `each_vowel {|v|puts v}` you will get an argument error, since
the method will expect a normal object, not a block.

What does it mean to have a method that takes a code block?

At first approximation you can think of a code block as an anonymous method.
You are writing a method that can take another method as an argument.

%w{a e i o u}.each { |vowel| code_block.call(vowel) }

Then it takes an array of vowels, which call the each method to pass each
one into the following block through |vowel| as a block argument. The block
arguments are then called by the variable code_block (I don't understand
this).

code_block.call(vowel) is calling the method stored in the code_block
variable, and
passing it the argument called vowel. When you call each_vowel like this:

each_vowel {|vowel| puts vowel}

The block with 'puts' is stored as code_block, and run 5 times, once
for each letter in the array:
%w{a e i o u}.each { |vowel| code_block.call(vowel) }

So the end result is that each vowel is printed out.

HTH,
-Adam

···

On 8/28/08, Brian Ross <p.brian.ross@gmail.com> wrote:

Brian Ross wrote:

From Beginning Ruby:

def each_vowel(&code_block)
  %w{a e i o u}.each { |vowel| code_block.call(vowel) }
end
each_vowel { |vowel| puts vowel }

I am trying to figure out how that works but I'm still having a bit of
trouble. Could someone break it down bit by bit to show what it's doing?

def each_vowel(&code_block)

It defines a method that takes a code block (is the & necessary?). What does
it mean to have a method that takes a code block?

  %w{a e i o u}.each { |vowel| code_block.call(vowel) }

Then it takes an array of vowels, which call the each method to pass each
one into the following block through |vowel| as a block argument. The block
arguments are then called by the variable code_block (I don't understand
this).

Brian

Code (in the form of Proc objects and similar) can be stored in a variable.

>> code = proc { puts "test" }
=> #<Proc:0xb7b03030@(irb):25>
>> code.call
test
=> nil
>>

The &argument to each_vowel is a local variable that stores any block or closure passed to it using the special method() { syntax }. After that, calling argument.call is the same as code.call in the previous example.

I got a little turned around in your question, either I'm just not understanding it or you're using a term wrong. The each method itself takes a block, the block is everything in the { curly braces }. The argument to the block is |vowel|, for every vowel in the array, the code block passed to each is called with that vowel passing it in |vowel|. That code block then goes an calls the code_block argument, which in turn contains the code block given when you called each_vowel.

I can see how that explanation gets a little confusing. Two things are called vowel, there are three things called a "code block," and a few layers of calls through the code blocks. This example may be simpler. It duplicated the Fixnum#times method.

>> def this_many_times(n,&block)
>> n.times { block.call }
>> end
=> nil
>> this_many_times(10) { puts "test" }
test
=> 10

···

--
Michael Morin
Guide to Ruby

Become an About.com Guide: beaguide.about.com
About.com is part of the New York Times Company

From Beginning Ruby:

def each_vowel(&code_block)
  %w{a e i o u}.each { |vowel| code_block.call(vowel) }
end
each_vowel { |vowel| puts vowel }

First, I'd like to show a simplified version of it. I think this works:

def each_vowel
  %w{a e i o u}.each { |vowel| yield vowel }
end

In the simplest form, to define a method that takes a code block, you can
ignore the block until you need it, and then call it with "yield". This will
actually execute faster, but it's not as flexible.

You can also call 'block_given?' to find out if you have a block.

So...

It defines a method that takes a code block (is the & necessary?).

Strictly, no.

What does
it mean to have a method that takes a code block?

ALL methods can take a code block. Most of them don't do anything with it. You
can verify this:

"foo".length {|x| raise "THIS BLOCK SHOULD NEVER BE CALLED!!!" }

So, with that in mind, the &foo says that you're binding whatever code block
was passed in to a local variable, so you can do things to it.

  %w{a e i o u}.each { |vowel| code_block.call(vowel) }

%w{a e i o u}, of course, translates to ['a', 'e', 'i', 'o', 'u']

The rest is a simple each loop. You could also do this:

['a', 'e', 'i', 'o', 'u'].each do |vowel|
  puts 'I got a vowel!'
  puts vowel
end

That block runs once for each vowel. To make it simpler, you could disregard
all the less common vowels, and just use 'e':

def each_important_vowel(&code_block)
  code_block.call('e')
end

If you're using it like in your example:

each_vowel {|vowel| puts vowel}

The easiest thing to do is to think of the code block as a function in its own
right. (It's not, which is one of the more disappointing things about Ruby,
but we can pretend that it is.)

So, it's really more like this:

def my_code_block(vowel)
  puts vowel
end
%w{a e i o u}.each {|vowel| my_code_block(vowel) }

If you made it through that, I'd like to justify my claim that yielding isn't
as flexible as the &block syntax. I'd say, yield when you can, and use &block
when you need to.

One example would be stored callbacks. I'm not sure what you've done with
classes and objects, so I'll simplify this:

before_printing_callbacks =
def before_printing &block
  before_printing_callbacks.push(block)
end

# Call it a few times, with various arguments...
# Then take a look at what's in that array.

def print_stuff string
  before_printing_callbacks.each do |block|
    block.call
  end
  print string
end

···

On Thursday 28 August 2008 12:12:07 Brian Ross wrote:

Intuitively I'd think that:

each_vowel {|vowel| puts vowel}

would lead to something that looked like:

%w{a e i o u}.each { |vowel| |vowel| puts vowel.call(vowel) }

which is incomprehensible to me. I guess I am trying to really figure out
how it's working so that I can construct my own and really understand it. To
sound like an idiot: I still don't really understand how it's working.

Brian

···

On Thu, Aug 28, 2008 at 1:36 PM, Adam Shelly <adam.shelly@gmail.com> wrote:

code_block.call(vowel) is calling the method stored in the code_block
variable, and
passing it the argument called vowel. When you call each_vowel like this:

each_vowel {|vowel| puts vowel}

The block with 'puts' is stored as code_block, and run 5 times, once
for each letter in the array:
%w{a e i o u}.each { |vowel| code_block.call(vowel) }

So the end result is that each vowel is printed out.

Thank you, everyone. If I understand correctly:

&foo just means that whatever is passed to it (& requires a code block) will
be saved as a local variable that may be used later.

The call method executes the block that it acts on and then executes it but
first assigns the block's | block argument | to the parameter passed to it.

Is it then that yield functions the same as the call method? I haven't quite
gotten to proc objects yet, but it looks like using & converts the code
block into an object, but yield, strictly, doesn't? Are code blocks the
exception to the "everything in ruby is an object" rule?

I'm certainly understanding this far better than I was previously, I think.

Brian

Alternatively, if I just run

puts each_vowel {}

it returns 5 vowels, each on its own line and seems to function the same as:

each_vowel {|vowel| puts vowel}

Maybe my question is, what is the importance of the second |vowel|? Does the
first block argument just get passed to the second block through whichever
block argument is given in the second? Also I'm having trouble with the
documentation for the call method to figure out how it works.

Brian

···

On Thu, Aug 28, 2008 at 3:27 PM, Brian Ross <p.brian.ross@gmail.com> wrote:

I guess I am trying to really figure out
how it's working so that I can construct my own and really understand it.
To
sound like an idiot: I still don't really understand how it's working.

>
> The block with 'puts' is stored as code_block, and run 5 times, once
> for each letter in the array:
> %w{a e i o u}.each { |vowel| code_block.call(vowel) }
>
> So the end result is that each vowel is printed out.
>

Intuitively I'd think that:

each_vowel {|vowel| puts vowel}

would lead to something that looked like:

%w{a e i o u}.each { |vowel| |vowel| puts vowel.call(vowel) }

which is incomprehensible to me. I guess I am trying to really figure out
how it's working so that I can construct my own and really understand it. To
sound like an idiot: I still don't really understand how it's working.

I'm probably not the best explainer... but you are on the right track.
Michael is right that having two things called vowel here can be
confusing. So let's rename the variables - the code will work
exactly the same:

def each_vowel &code_block
%w{a e i o u}.each {|item| code_block.call(item) }
end
each_vowel {|v| puts v}

code_block.call(item) simply executes the block using 'item' in place
of the variable inside the || pipes, so conceptually, this 'expands'
to the following pseudo-code:

%w{a e i o u}.each { |item| {|v=item| puts v}}

Alternatively, if I just run
puts each_vowel {}
it returns 5 vowels, each on its own line and seems to function the same as:
each_vowel {|vowel| puts vowel}

Something completely different is happening with `puts each_vowel{}`.
Remember that Ruby methods return the result of the last line, which
for each_vowel, is the result of Array.each, which is the array
itself. So after executing an empty block, which does nothing, you
are returning the array and passing that to puts. To see the
difference, compare to :
each_vowel{|v| p v.succ}

-Adam

···

On 8/28/08, Brian Ross <p.brian.ross@gmail.com> wrote:

On Thu, Aug 28, 2008 at 1:36 PM, Adam Shelly <adam.shelly@gmail.com> wrote:

As far as I understand it, passing a parameter to a method prefixed with &,
or the return value of 'lambda', creates or passes in
a Proc object which can continue to be called after the original function
call has gone out of scope i.e. a closure.

Yield by contrast is a way of communicating with a code block inside a
method, and the block can talk back. More useful
in iterations, transactions and so on.

···

On Fri, Aug 29, 2008 at 10:14 PM, Brian Ross <p.brian.ross@gmail.com> wrote:

Thank you, everyone. If I understand correctly:

&foo just means that whatever is passed to it (& requires a code block)
will
be saved as a local variable that may be used later.

The call method executes the block that it acts on and then executes it but
first assigns ttiuohe block's | block argument | to the parameter passed to
it.

Is it then that yield functions the same as the call method? I haven't
quite
gotten to proc objects yet, but it looks like using & converts the code
block into an object, but yield, strictly, doesn't? Are code blocks the
exception to the "everything in ruby is an object" rule?

I'm certainly understanding this far better than I was previously, I think.

Brian