Search code examples
arraysrubyproc

Ruby - How to write a method that accepts a proc with varying numbers of params?


I am writing an Array#map! method in Ruby that should accept a proc:

def map!(&blck)

    (0..self.length-1).each do |i|
        self[i] = blck.call(i)
    end

    self
end

This works fine if the proc accepts 1 parameter, but not if there are several (or if it accepts the character as opposed to the index). Two proc examples:

prc1 = Proc.new do |ch|

    if ch == 'e'
        '3'
    elsif ch == 'a'
        '4'
    else
        ch
    end

end

and

prc2 = Proc.new do |ch, i|

    if i.even?
        ch.upcase
    else
        ch.downcase
    end

end

Is there a way to do this?


Solution

  • You can always find out how many arguments that Proc takes:

    def map!(&block)
      case block.arity
      when 1
        # Takes 1 argument
      when 2
        # Takes 2 arguments
      else
        # etc.
      end
    end
    

    This is a common pattern if you need to handle different argument counts in a particular way.

    It's worth noting that unless you need to shuffle up the order of the arguments passed in you can always pass in too many and the excess will be ignored:

    def example(&block)
      block.call(1,2,3)
    end
    
    example { |v| p v }
    # => 1