Hello,
I'm currently experimenting a bit in Ruby, to get a feeling of how the language works. Out of curiosity, I wanted to have a method which would accept a Proc ( or block/ lambda/ Method ) both passed attached or as an explicit parameter. My idea to realise this was:
def test( block_as_parameter= nil, &block_attached )
block = block_attached || block_as_parameter
block.call
end
test { puts "Foo" } #=> Foo
test( Proc.new { puts "Foo" } ) #=> Foo
So far, so good (I even think that this is the easiest way to achieve said functionality). This works as long as I don't have the splat operator in my parameter list. There are - afaict - two reasons for this:
1.: After the splat operator it is not possible to specify optional parameters (and even if we had the block_as_parameter parameter before the splat, it would take precedence over it, resulting in 2. - also, it would destroy interface consistency).
2.: The block_as_parameter parameter will be filled with one of the parameters which we wanted the splat operator to gather.
My code to solve this problem is as follows:
def test2( foo, *args, block_as_param, &block_attached )
block = #this is where the magic happens
if block_attached
args << block_as_param
block_attached
else
block_as_param
end
p foo
p args
block.call
end
test2( "FirstParam", "SecondParam" ) { puts "Foo" }
#=> "FirstParam"
# ["SecondParam"]
# Foo
test2( "FirstParam", "SecondParam", "ThirdParam" ) { puts "Foo" }
#=> "FirstParam"
# ["SecondParam", "ThirdParam"]
# Foo
test2( "FirstParam", "SecondParam", "ThirdParam", Proc.new { puts "Foo" } )
#=> "FirstParam"
# ["SecondParam", "ThirdParam"]
# Foo
This solution works as I want it to work, so that's good. But now I'm curious: Is there another, easier way to achieve what I want? I'm aware that this has not that many real-life usages, but I think it's an interesting scenario to think about.
Thanks in advance for all your ideas!
P.S.: Tested in Ruby 1.9.3, so I can't tell if this would behave any different in Ruby 1.8.