Blocks in Procs?


#1

Hi all, I have been using a lot of Proc’s and lambda’s lately and I have
encountered something a little baffling. It might be syntax or a
misunderstanding of the language; would anyone mind helping me out?

I expect the following to print “Hello World”, but it does not:

#!/usr/bin/env ruby

x = Proc.new { |a| p( block_given? ? yield(a) : a ) }
x.call( ‘World’ ) { |b| p “Hello #{b}” }

Likewise, in continuation:

y = Proc.new { |b| p “Hello #{b}” }
p x.call( ‘World’, &y )

this may be related, it returns false instead of nil… what gives?

p x.call( ‘World’ ) &y

END

I have nothing to offer but a thank you.

  • travis

#2

On May 16, 2006, at 10:17 PM, travis michel wrote:

#!/usr/bin/env ruby

x = Proc.new { |a| p( block_given? ? yield(a) : a ) }
x.call( ‘World’ ) { |b| p “Hello #{b}” }

I don’t believe you can pass a block argument when calling a Proc.
It is silently ignored.
In your case the call to block_given? would be relative to the scope
where Proc.new is called and not relative to the arguments passed
when the block is executed via Proc#call. This is changing in Ruby
1.9 I believe so that block arguments can be provided to blocks when
called via yield and/or Proc#call.

Likewise, in continuation:

y = Proc.new { |b| p “Hello #{b}” }
p x.call( ‘World’, &y )

Same problem, a block argument is ignored by Proc#call.

this may be related, it returns false instead of nil… what gives?

p x.call( ‘World’ ) &y

x.call(‘World’) returns nil because the return value of the Proc is
the last expression evaluated in the block which is a call to
Kernel#p, which always returns nil.

So now you have:

p nil &y

which is getting parsed as a call to the bitwise and operator (nil &
y), which returns false.

Gary W.


#3

Thank you very much Gary! /me crosses fingers for support in 1.9


#4

travis michel wrote:

Thank you very much Gary! /me crosses fingers for support in 1.9

It’s already there, I think.

Cheers,
Dave


#5

On 17/05/06, travis michel removed_email_address@domain.invalid wrote:

I expect the following to print “Hello World”, but it does not:

#!/usr/bin/env ruby

x = Proc.new { |a| p( block_given? ? yield(a) : a ) }
x.call( ‘World’ ) { |b| p “Hello #{b}” }

Is this any use to you?

x = Proc.new { |*a| a[1] ? a[1].call(a[0]) : a[0] }
p x.call( ‘Boo’ )
p x.call( ‘World’, Proc.new{ |b| “Hello #{b}” } )

“Boo”
“Hello World”

Regards,
Paul.