Search code examples
rubyextension-methodsoverloadingruby-1.9.3enumerator

How to extend Ruby Enumerable class max_by to ignore nil?


a = [4, 3, 2, nil]
a.max_by { |v| v * 2 } => NoMethodError: undefined method `*' for nil:NilClass

How to overload max_by to ignore nil values?


Solution

  • Welcome to Ruby: there are so many ways to solve the problem!

    A very simple solution is:

    a.max_by { |v| v.to_f * 2 }
    

    since nil coerces to float as 0. This doesn't handle negative values, but since nil is only a single instance of a class called NilClass, now as with all classes in Ruby we can open it an let it learn a littly maths:

    class NilClass
      # overloading * operator
      def *(y)
        # returning negative infinity: Ruby 1.8.7
        -1.0/0.0
        # returning negative infinity: Ruby 1.9.2
        # -Float::INFINITY
      end
    end
    

    now we have

    a.max_by { |v| v * 2 }
    

    returning 4.