0

Let’s say I have this method num_i_want?, and I want to use it with select to filter my nums array.

def num_i_want?(num)
  num % 2 == 0
end

nums = [1, 2, 3, 4]

I try to use the method as a block using the unary ampersand operator:

nums.select( &num_i_want? )

But I get this error:

ArgumentError: wrong number of arguments (0 for 1)
    from (irb):1:in `num_i_want?'
    from (irb):6

Why am I getting this error? And what is the simplest code I can use instead?

I know that &:num_i_want? doesn’t work. That tries to call num_i_want? on each number, which raises NoMethodError because Integer#num_i_want? doesn’t exist.

Of course, I could use &:even? to call Integer#even?, but let’s pretend the implementation of num_i_want? is more complicated than that.

Rory O'Kane
  • 29,210
  • 11
  • 96
  • 131
  • See @UriAgassi's answer [here](http://stackoverflow.com/questions/23695653/can-you-supply-arguments-to-the-mapmethod-syntax-in-ruby/23711606#23711606). (Not a dup.) – Cary Swoveland Sep 16 '15 at 21:42

1 Answers1

1

When you write

nums.select( &num_i_want? )

your code is actually being parsed like & num_i_want?(). First num_i_want? is called with no arguments, and then the ampersand operator is applied. Your problem is that you can’t refer to a method directly by name.

The simplest way to refer to a method is by passing a symbol to Object#method:

nums.select( &method(:num_i_want?) )
#=> [2, 4]

If you are worried that using Object#method combined with & makes the code too clever and hard-to-read, the alternative is passing a normal block that just wraps num_i_want?:

nums.select { |num| num_i_want?(num) }
#=> [2, 4]
Rory O'Kane
  • 29,210
  • 11
  • 96
  • 131