0

I would like to pass an array as an argument with many values as possible for this method. For example, if I entered [1,2,3] into add([1,2,3], I should receive the sum value of the array.

def add(a, b)
    a + b
end

def subtract(a, b)
a - b
end

Since I am new to Ruby, I am not sure how to go about this. Can someone please explain.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
visBar
  • 171
  • 1
  • 1
  • 8

3 Answers3

12

The usual way of doing this is to pass a variable number of arguments, which I assume from your question are Numeric:

def add_em_up(*args)
  args.reduce(:+)
end

add_em_up(1,2,3,4)    #=> 10
add_em_up(1,2,3.5,4)  #=> 10.5
Cary Swoveland
  • 106,649
  • 6
  • 63
  • 100
  • +1 for `#reduce` and +1 for *Greedy* operator. It is really greedy..Huhh.. :-) – Arup Rakshit Jul 09 '14 at 10:23
  • 1
    I find this a bit amusing. 18 hours after posting I've received 10 upvotes for an answer that falls somewhat short of, let's say, "mind-bending", yet many brilliant contributions I've made in the past have yet to earn a single +1. I guess that's just life at SO. – Cary Swoveland Jul 09 '14 at 18:05
  • I agree, It is SO life :-) – Arup Rakshit Jul 09 '14 at 18:10
2

I think Andrew's post is fine but you're more likely to see the is_a method like this:

def add(val)
  if val.is_a?(Array)
    do something
  else
    @result += val
  end
end
Anthony
  • 15,435
  • 4
  • 39
  • 69
1

Looking at your earlier question, I'm guessing you want to be able to distinguish between array arguments and numeric arguments. Try using the kind_of? method and branching based on the result. See this question for other advice (using the responds_to? method is more idiomatic).

def add(val)
  if (val.kind_of?(Array))
    # add each element
  else
    @result += val
  end
end

To do the addition, you'll want to use the each method to perform an action for every element of the array.

val.each do |x|
  @result += x
end
Community
  • 1
  • 1
Andrew
  • 1,839
  • 14
  • 25
  • 2
    Why bother with the `kind_of?`, just go straight for `if val.respond_to? :each` – ian Jul 09 '14 at 00:01
  • @iain No. I would use `#instance_of?`.. There are lots who can respond to `#each`.. Or, You can either do `respond_to?(:to_ary)`... `#kind_of` for *kindness* and `#instance_of?` for *strictness*.. :-) It is up to you what you want to be.. Loll. – Arup Rakshit Jul 09 '14 at 10:26
  • 1
    Yeah, I wanted to answer the question literally just in case visBar later wanted to distinguish between other collections. You wouldn't want to do the same kind of `each` over an array and a hash. – Andrew Jul 09 '14 at 16:02
  • @ArupRakshit There *are* lots that can respond to `each`, so document the default usage (for an Array-like collection) and let the method take a block too, the caller should know what it's passing. Use `instance_of` for something like this in a codebase I'm responsible for and you wouldn't get past a code review ;) – ian Jul 10 '14 at 00:04