views:

350

answers:

2

Hi there. I have a rather unusual use case whereby I need to be able to obtain the number of parameters a given block has been defined to take. For example...

foobar(1,2,3) { |a, b, c|
}

def foobar(x, y, z, &block)
  # need to obtain number of arguments in block
  # which would be 3 in this example
end

From what I understand, this is possible in the 1.9 trunk, but not in any official release. I was hoping if there's any way to do this without having to download a separate gem/extension module. Thank you.

+8  A: 

When you materialize a block with &, it becomes a Proc object, which has an arity method. Just be careful - it returns the one's complement if the proc takes a *splat arg.

def foobar(x, y, z, &block)
  p block.arity
end

(Answer via "The Ruby Programming Language" book.)

Justin Love
you beat me to it :) +1
Gishu
Right. Note that `{ || nil }` will have an arity of 0, but `{ nil }` will have an arity of -1.
Curt Sampson
Hi Justin, thanks for the answer, this is exactly what I needed :)
Exponent
+3  A: 

Is this what you're looking for...

def foobar(x, y, z, &block)
  # need to obtain number of arguments in block
  # which would be 3 in this example
  case block.arity
    when 0 
      yield "i have nothing"
    when 1
      yield "I got ONE block arg"
    when 2
      yield "I got TWO block args"
    when 3
      yield "I got THREE block args"
  end
end

foobar(1,2,3) { |a, b, c|
    puts a
}

Outputs:

D:\ruby\bin>ruby -v
ruby 1.8.6 (2007-09-24 patchlevel 111) [i386-mswin32]

D:\ruby\bin>ruby c:\Temp.rb
I got THREE block args

See also - A Ruby HOWTO: Writing A Method That Uses Code Blocks from codahale.com

Gishu
Hi Gishu. Thanks for the article, I'll definitely need to read through this.
Exponent