Gavin Kistner
2/7/2007 2:57:00 PM
On Feb 6, 10:41 pm, "Alex Strasheim" <astra...@gmail.com> wrote:
> And if we were going to pass a parameter when we run @action.call,
> wouldn't the block of code need to have a parameter in it? Like this:
>
> start_button = JukeboxButton.new("Start") { |x| songlist.start }
Michael answered the brunt of your question as I would have ("ignore
the self"), but I wanted to answer the above question of yours.
While methods in Ruby are pretty adamant about getting exactly the
number of parameters you define (except when you explicitly provide
default values or explicitly ask to collect any 'extra' values into an
array), blocks are much more forgiving. See the following code:
def block_to_proc( &blok )
blok
end
no_arg = block_to_proc{ 'foo' }
one_arg = block_to_proc{ |x| "foo-#{x.inspect}" }
only_one_used = block_to_proc{ |x,y| "foo-#{x.inspect}" }
two_arg_used = block_to_proc{ |x,y| "foo-#{x.inspect}-
#{y.inspect}" }
puts no_arg.call
#=> foo
puts no_arg.call( 'bar' )
#=> foo
puts one_arg.call
#=> warning: multiple values for a block parameter (0 for 1)
#=> foo-nil
puts one_arg.call( 'bar' )
#=> foo-"bar"
puts one_arg.call( 'bar', 'jim' )
#=> foo-["bar", "jim"]
#=> warning: multiple values for a block parameter (2 for 1)
puts only_one_used.call
#=> foo-nil
puts only_one_used.call( 'bar' )
#=> foo-"bar"
puts only_one_used.call( 'bar', 'jim' )
#=> foo-"bar"
puts only_one_used.call( 'bar', 'jim', 'jam' )
#=> foo-"bar"
puts two_arg_used.call
#=> foo-nil-nil
puts two_arg_used.call( 'bar' )
#=> foo-"bar"-nil
puts two_arg_used.call( 'bar', 'jim' )
#=> foo-"bar"-"jim"
puts two_arg_used.call( 'bar', 'jim', 'jam' )
#=> foo-"bar"-"jim"
Note that the above behaves the same if you use Proc.new instead of
the block_to_proc function. In 1.8.6, if you use 'proc' or 'lambda'
instead, the no_arg and one_arg examples work the same, but you get an
ArgumentError ("wrong number of arguments (0 for 2)") raised and
halting your program when you try to call only_one_used without any
arguments. (And if you comment that out, you also get that same error
when you try to call it with too many arguments.)
I provide the above without any justification for the behavior. :)
This is with Ruby 1.8.6.
My own question: what rationale allows the one-argument Proc 'auto-
splat' the extra arguments into an array, but the two-argument case
does not? And what changes in 1.9 (besides 'proc' becoming another way
of performing 'Proc.new' instead of 'lambda')?