Are there more elegant ways to prevent negative numbers in Ruby?

左心房为你撑大大i 提交于 2019-12-04 04:31:37

问题


Given that I'd like to do the following calculation:

total = subtotal - discount

Because discount might be greater than subtotal, there is code like the following:

class Calculator
  def initialize(subtotal: subtotal, discount: discount)
    @subtotal = subtotal
    @discount = discount
  end

  def total
    [subtotal - discount, 0].max
  end

  private

  def subtotal
    @subtotal
  end

  def discount
    @discount
  end
end

When seeing the [subtotal - discount, 0].max part or any similar code, I often have to pause and think.

Are there more elegant ways to handle this kind of calculation?


回答1:


I think your solution is essentially correct, and probably the most readable besides a small refactor. I might change it slightly like so:

  def total
    final_total = subtotal - discount
    [final_total, 0].max
  end

The ruby expression [final_total, 0].max is essentially the traditional solution in mathematics for the same function: max {final_total, 0}. The difference is just notation and context. Once you see this max expression once or twice you can read it as follows: "final_total, but at least zero".

Perhaps if you use this expression more than once you can add another at_least_zero method or something like in Shiko's solution.




回答2:


Thinking we can extend the Numeric class?

class Numeric                                                                  
  def non_negative                                                             
    self > 0 ? self : 0                                                                      
  end                                                                          
end                                                                            

class Calculator
  def initialize(subtotal: subtotal, discount: discount)
    @subtotal = subtotal
    @discount = discount
  end

  def total
    (@subtotal - @discount).non_negative
  end
end



回答3:


A plain if statement might be easier to understand:

def total
  if discount > subtotal
    0
  else
    subtotal - discount
  end
end



回答4:


Just to clarify more, we need to add classes to be extended in core_ext.rb . file :
1) Create core_ext.rb file under config\initializers folder in your project.
2) Paste below as mentioned by @songyy in his answer:

class Numeric                                                                  
  def non_negative                                                             
    self > 0 ? self : 0                                                                      
  end                                                                          
end    

Reference:
https://guides.rubyonrails.org/plugins.html#extending-core-classes



来源:https://stackoverflow.com/questions/31530404/are-there-more-elegant-ways-to-prevent-negative-numbers-in-ruby

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!