Home > other >  Why is this method not returning nil when a and b are equal?
Why is this method not returning nil when a and b are equal?

Time:09-15

This method should return the sum of all numbers between a and b (not ordered) and should return a or b if they are equal.

def get_sum(a,b)
  a < b ? (a..b).sum : (b..a).sum
end

I'm curious as to why this method doesn't return nil when a and b are equal. The ternary operator takes care of the condition where a is less than or greater than b so I'm tempted to add return a if a==b before the ternary to test if they are equal but it appears it's not necessary.

For example, if a=5 and b=5 then the value returned is 5. Could someone explain why this is please?

CodePudding user response:

This is just how the < operator (or rather method) works.

a < b

It returns true if a is less than b, otherwise it returns false.

Therefore 5 < 5 returns false.

By writing a..b you create a Range object Range.new(a, b), which starts at a and goes up to and including b. Afterwards you call the sum method on this object.

Since the range 5..5 goes from 5 to and including 5, when you convert it to an array you get:

(5..5).to_a #=> [5]

And the sum method adds all numbers which are within this range. And since this range includes a single number 5, the result of this operation is 5.

(5..5).sum #=> 5

Your method could written more concisely

def get_sum(a, b)
  (a < b ? a..b : b..a).sum
end

To make it return 0 when a and b are the same, you could use a exclusive range with three dots ....

def get_sum(a, b)
  (a < b ? a...b : b...a).sum
end

get_sum(5, 5) #=> 0
get_sum(5, 6) #=> 5
get_sum(5, 7) #=> 11

CodePudding user response:

In fact there is no Range#sum because it is inherited from Enumerable#sum

So (5..5).sum it is the same as (5..5).to_a.sum

(5..5).to_a # => [5]

That's the reason

To fix it you can do something like this (change else branch of your ternary operator to elsif)

def get_sum(a, b)
  if a < b
    (a..b).sum
  elsif a > b
    (b..a).sum
  end
end

get_sum(1, 2) # => 3
get_sum(2, 1) # => 3
get_sum(5, 5) # => nil

But in my opinion get_sum(5, 5) == 5 is more clear than nil

CodePudding user response:

the ternary operator has only two branches. if the condition is not truthy the latter is executed. there are no cases where no branches are executed (unless some error happens but that's another case).

you get nil only if you have only a branch and that's not executed. e.g.

def get_sum(a,b)
  if a < b  
    (a..b).sum
  end
end

for get_sum(5, 5) this evaluates to nil

  • Related