Newbie understanding blocks

I am learning Ruby and having some difficulty understanding blocks. I
was trying out following code for getting better idea about blocks. I
was expecting case 2 to print ‘test’ string, but it is not printing
out anything. Any elaboration on what’s happening here would be really
helpful.

case 1:
{{{

num1 = 1.22
=> 1.22

num1.round {|a| puts a}
=> 1
}}}

case 2:
{{{

num1 = 1.22
=> 1.22

num1.round {|a| puts “test”}
=> 1

}}}

I am using Ruby on Mac OSX - ruby 1.8.7 (2009-06-12 patchlevel 174)
[universal-darwin10.0].


neuby.r

On 03/19/2011 11:43 PM, Neubyr N. wrote:

num1.round {|a| puts a}
}}}
The round method does not use a block. As with most methods that don’t
mention they use blocks in their documentation, the block given is
simply ignored.

In both of the cases you listed above, the output you see after calling
the round method is the value returned by that method. irb always
prints the value of the last executed statement. The blocks you gave in
both cases were silently discarded and never executed.

If you would like to play around a bit with blocks, try using the each
method on an array:

irb(main):001:0> arr = [1,2,3,4]
=> [1, 2, 3, 4]
irb(main):002:0> arr.each { |a| puts a }
1
2
3
4
=> [1, 2, 3, 4]
irb(main):003:0> arr.each { |a| puts “test” }
test
test
test
test
=> [1, 2, 3, 4]

Note that the output generated by the blocks in both cases is displayed
before the =>. Everything following the => on its line is the value
returned by the last statement. In each of the 3 statements above, the
resulting value is the array created in the first line.

-Jeremy

Jeremy B. wrote in post #988377:

On 03/19/2011 11:43 PM, Neubyr N. wrote:

num1.round {|a| puts a}
}}}
The round method does not use a block. As with most methods that don’t
mention they use blocks in their documentation, the block given is
simply ignored.

In both of the cases you listed above, the output you see after calling
the round method is the value returned by that method. irb always
prints the value of the last executed statement. The blocks you gave in
both cases were silently discarded and never executed.

If you would like to play around a bit with blocks, try using the each
method on an array:

irb(main):001:0> arr = [1,2,3,4]
=> [1, 2, 3, 4]
irb(main):002:0> arr.each { |a| puts a }
1
2
3
4
=> [1, 2, 3, 4]
irb(main):003:0> arr.each { |a| puts “test” }
test
test
test
test
=> [1, 2, 3, 4]

Note that the output generated by the blocks in both cases is displayed
before the =>. Everything following the => on its line is the value
returned by the last statement. In each of the 3 statements above, the
resulting value is the array created in the first line.

-Jeremy

Thanks for explaining it in detail Jeremy. That’s helpful.

I had played with ‘Array.each {block}’ as most of the examples/book had
pointed out. But I couldn’t understand how arguments are being passed to
blocks, so I started playing with some scalar variables (objects??). I
had referred to ri for some documentation, but didn’t pay attention to
block-calls.

So a block is dependent on method preceding it, whose output gets passed
as args to block?? Sorry if that’s really silly question.


thanks,
neuby.r

Great! Thanks a lot for explaining the workflow here - I wasn’t
following how methods and blocks were interacting together. Now it’s
making a lot more sense to me.


neuby.r

On 03/20/2011 12:33 AM, Neubyr N. wrote:

Thanks for explaining it in detail Jeremy. That’s helpful.

I had played with ‘Array.each {block}’ as most of the examples/book had
pointed out. But I couldn’t understand how arguments are being passed to
blocks, so I started playing with some scalar variables (objects??). I
had referred to ri for some documentation, but didn’t pay attention to
block-calls.

So a block is dependent on method preceding it, whose output gets passed
as args to block?? Sorry if that’s really silly question.

No, think of a block as yet another argument to a method. The value of
the method’s result is not necessarily what is passed in. It can be
anything that the method is written to pass in. You might find that
writing a method that takes a block to be helpful:

def use_a_block
yield(42)
end

use_a_block { |value| puts value }

The yield keyword calls the block given to the method and passes any
arguments given to the yield over to the block (in this case 42). The
return value of the block becomes the return value of the yield keyword.
The block acts sort of like an anonymous method that you can tell the
called method to use.

Here is a slightly more interesting example:

def use_a_block2(bool)
if bool
yield(42)
else
yield(“hello”)
end

“This is the return value of use_a_block2”
end

puts(use_a_block2(true) { |value| puts value })
puts(use_a_block2(false) { |value| puts value })

-Jeremy

You can think of a block as a method with no name. A block gets passed
to another method, and that other method executes the block using a
yield
statement with the specified arguments:

def my_meth(x)
yield(10, x) #specified arguments
end

my_meth(5) do |s, t| #the parameters of the block get assigned
puts s+t #the arguments in the yield()
end

–output:–
15

Unless you know what the yield() statement looks like, you don’t know
how how many parameters you should define your block with (0? 1? 2?).
The docs tell us that the each() method for an array ‘yields’ each
element of the array to the
block in turn, i.e. the block you supply should take one argument.

You will learn that there is a special syntax that allows you to capture
a block in a
variable:

def my_meth(x, &my_block) #the block will get assigned to my_block
my_block.call(x) #the block is executed with the call() method
end

my_meth(“Joe”) do |y|
puts “Hello #{y}”
end

–output:–
Hello Joe