1

I'm working on a very simple exercise: a method that can multiply between two and an indefinite number of floats. My first idea for doing this was to use the splat operator:

def multiply a, b, *rest
  a * b * rest
end

That was unsuccessful. I then tried this:

def multiply *numbers
  total = 1
  numbers.each do |x|
   total = total * x 
  end
  total
end

The above is almost successful—the problem is that it will accept a single argument, and I want it to require at least two. How can I achieve this?

achalk
  • 3,229
  • 3
  • 17
  • 37

1 Answers1

4

There are many options. The one the author of the exercise probably intended for you to use is inject:

def multiply(*numbers)
  numbers.inject(&:*)
end

This will cause the same problem as your second implementation of multiply in that it will accept 0 or 1 arguments. You can fix this by simply raising an ArgumentError if you don't have at least two:

def multiply(*numbers)
  raise ArgumentError unless numbers.length >= 2
  numbers.inject(&:*)
end

You can go the other way and accept two actual arguments and splat the rest, and simply build the complete array you intend to multiply together:

def multiply(a, b, *rest)
  [a, b, *rest].inject(&:*)
end
user229044
  • 232,980
  • 40
  • 330
  • 338
  • It's worth pointing out that you can also pass a string as the second argument to `raise`, which can serve as a helpful message. – Sagar Pandya Feb 03 '17 at 01:46
  • Super, thank you. I didn't know about `inject`. Can you explain the `(&:*)` notation that follows the method? – achalk Feb 03 '17 at 01:49
  • 1
    @adc See https://stackoverflow.com/questions/1961030/ruby-ampersand-colon-shortcut – user229044 Feb 03 '17 at 01:50
  • @adc the shorthand works a little differently for inject/reduce than for each/map/etc., see http://stackoverflow.com/questions/14526290/are-there-any-additional-inject-shorthand as well – max pleaner Feb 03 '17 at 03:38
  • You could also use `a * b * rest.inject(1, &:*)`, to avoid unpacking and packing `rest`. – Eric Duminil Feb 03 '17 at 08:42