Blocks and Closures

If this is covered elsewhere, please point me in the right direction.

Either why, my question is what exactly is the difference between a
block / closure of the syntax
do |x, y|

end

versus

{|x, y|

}

Are these idioms identical in all but their syntax? Or is there an
underlying difference to them?

This has been bugging me for a while, and I haven’t been able to
locate the answer in the docs I’ve found.

Thanks!

Alex McHale

Alex McHale wrote:

If this is covered elsewhere, please point me in the right direction.

Either why, my question is what exactly is the difference between a
block / closure of the syntax
do |x, y|

end

versus

{|x, y|

}

Are these idioms identical in all but their syntax? Or is there an
underlying difference to them?

This has been bugging me for a while, and I haven’t been able to
locate the answer in the docs I’ve found.

The only difference is precedence:

def foo(*args, &bl)
puts “foo got the block” if bl
end

def bar(*args, &bl)
puts “bar got the block” if bl
end

foo bar {} # ==> bar got the block
foo bar do end # ==> foo got the block

Alex McHale wrote:

Are these idioms [“foo {…}” and “foo do … end”] identical in all
but their syntax? Or is there an underlying difference to them?

Mostly. There’s only a small difference in how they bind to methods:

irb(main):001:0> def foo(*args, &block); puts “foo got block” if block; end
irb(main):002:0> def bar(*args, &block); puts “bar got block” if block; end
irb(main):003:0> foo bar {}
bar got block
irb(main):004:0> foo bar do end
foo got block

Hope this helps. :slight_smile:

Thanks!

No problem.

Regards,
Florian Gross

Alright, while that is very confusing to me (not the concept, I
understand what you said, just why the precedence is different), you
raise another question.

In your example, you use the &bl syntax. I understand that if you
want the proc object, that is the syntax to use, but why use it in
that case?

Wouldn’t this give identical results?

def foo(*args)
puts “foo got the block” if yield
end

etc? Is the reason to use this construct because you want to demand
that a block be passed?

And on that note, is there a syntax to determine whether or a block
was passed to the method, in the syntax of my construct?

Thanks!

···

On Wed, 2 Jun 2004 05:23:30 +0900, Joel VanderWerf vjoel@path.berkeley.edu wrote:

Alex McHale wrote:

If this is covered elsewhere, please point me in the right direction.

Either why, my question is what exactly is the difference between a
block / closure of the syntax
do |x, y|

end

versus

{|x, y|

}

Are these idioms identical in all but their syntax? Or is there an
underlying difference to them?

This has been bugging me for a while, and I haven’t been able to
locate the answer in the docs I’ve found.

The only difference is precedence:

def foo(*args, &bl)
puts “foo got the block” if bl
end

def bar(*args, &bl)
puts “bar got the block” if bl
end

foo bar {} # ==> bar got the block
foo bar do end # ==> foo got the block

Alex McHale wrote:

Alright, while that is very confusing to me (not the concept, I
understand what you said, just why the precedence is different), you
raise another question.

In your example, you use the &bl syntax. I understand that if you
want the proc object, that is the syntax to use, but why use it in
that case?

Wouldn’t this give identical results?

def foo(*args)
puts “foo got the block” if yield
end

etc? Is the reason to use this construct because you want to demand
that a block be passed?

And on that note, is there a syntax to determine whether or a block
was passed to the method, in the syntax of my construct?

You’re right, there’s no reason to use the &bl notation. You can use the
Kernel#block_given? method:

def foo(*args)
puts “foo got the block” if block_given?
end

But using ‘if yield’ is different: it tests the return value of the
block, not the existence of the block.

Oooh I understand now. In fact I had given my own answer initially,
by noting that bl is the proc object.

Thank you for the clarification. I come to love Ruby more and more
every day …

For me, Ruby is a lot like vim. I’ve been using it for years, and I
still learn something new about it every day.

···

On Wed, 2 Jun 2004 05:38:19 +0900, Joel VanderWerf vjoel@path.berkeley.edu wrote:

Alex McHale wrote:

Alright, while that is very confusing to me (not the concept, I
understand what you said, just why the precedence is different), you
raise another question.

In your example, you use the &bl syntax. I understand that if you
want the proc object, that is the syntax to use, but why use it in
that case?

Wouldn’t this give identical results?

def foo(*args)
puts “foo got the block” if yield
end

etc? Is the reason to use this construct because you want to demand
that a block be passed?

And on that note, is there a syntax to determine whether or a block
was passed to the method, in the syntax of my construct?

You’re right, there’s no reason to use the &bl notation. You can use the
Kernel#block_given? method:

def foo(*args)
puts “foo got the block” if block_given?
end

But using ‘if yield’ is different: it tests the return value of the
block, not the existence of the block.

Just a note for the OP. The following example shows the advantage of
the &block notation in certain circumstances.

def bar
return 5 + yield
end

def foo(&block)
bar(block)
end

‘foo’ is now a proxy for ‘bar’.

Gavin

···

On Wednesday, June 2, 2004, 6:38:19 AM, Joel wrote:

You’re right, there’s no reason to use the &bl notation. You can use the
Kernel#block_given? method:

Gavin Sinclair wrote:

You’re right, there’s no reason to use the &bl notation. You can use the
Kernel#block_given? method:

Just a note for the OP. The following example shows the advantage of
the &block notation in certain circumstances.

def bar
return 5 + yield
end

def foo(&block)
bar(block)
end

‘foo’ is now a proxy for ‘bar’.

Slight nit: ‘bar(block)’ should be ‘bar(&block)’, if you want to
propagate the block.

Actually, though, there is a more efficient way to propagate a block:

def bar
return 5 + yield
end

def foo
bar {yield}
end

p foo {3} # ==> 8

I guess it’s more efficient because no Proc object is created. This
technique doesn’t work if you need to store the block somewhere for
later access. Then you really do need to use & or Proc.new.

Here’s some benchmarking (ruby-1.9.0):

require ‘benchmark’

def outer11(&bl)
inner1(&bl)
end

def outer12(&bl)
inner2(&bl)
end

def outer21
inner1 {yield}
end

def outer22
inner2 {yield}
end

def inner1(&bl)
bl.call
end

def inner2
yield
end

n = 100000

Benchmark.bmbm(10) do |rpt|
rpt.report(“outer11”) do
n.times {outer11{}}
end

rpt.report(“outer12”) do
n.times {outer12{}}
end

rpt.report(“outer21”) do
n.times {outer21{}}
end

rpt.report(“outer22”) do
n.times {outer22{}}
end
end

END

Output:

Rehearsal ---------------------------------------------
outer11 1.850000 0.010000 1.860000 ( 1.856130)
outer12 1.600000 0.000000 1.600000 ( 1.600134)
outer21 2.210000 0.000000 2.210000 ( 2.214836)
outer22 0.520000 0.000000 0.520000 ( 0.526088)
------------------------------------ total: 6.190000sec

             user     system      total        real

outer11 1.870000 0.000000 1.870000 ( 1.871797)
outer12 1.620000 0.000000 1.620000 ( 1.623072)
outer21 2.230000 0.000000 2.230000 ( 2.236854)
outer22 0.500000 0.000000 0.500000 ( 0.501914)

···

On Wednesday, June 2, 2004, 6:38:19 AM, Joel wrote: