Search code examples
rubytail-recursionfirst-class

Passing a comparison operator as argument to a method in Ruby


What would be the best way to pass a comparison operator as an argument to a method in Ruby? I wanted to create a generic sorted? recognizer for arrays, and pass either '<=', or '>=' to this method.

So far I have this code:

class Array
  def sorted?
    return 1 if sorted_increasing?
    return -1 if sorted_decreasing?
    0
  end

  def sorted_increasing?
    return true if length < 2
    self[0] <= self[1] && self.drop(1).sorted_increasing?
  end

  def sorted_decreasing?
    return true if length < 2
    self[0] >= self[1] && self.drop(1).sorted_decreasing?
  end
end

– it appears that it would be better to have a sorted_generic?(comparison_operator) method instead of sorted_increasing? and sorted_decreasing?.

Upd: Thank you for your replies, my solution looks as follows:

class Array
  def sorted?
    return 1 if sorted_generic?(:<=)
    return -1 if sorted_generic?(:>=)
    0
  end

  def sorted_generic?(comparison)
    return true if length < 2
    self[0].send(comparison, self[1]) &&
        self.drop(1).sorted_generic?(comparison)
  end
end

Solution

  • The comparison operators are just methods in Ruby, so you could do:

    1 <= 2 # is the same as
    1.<=(2)
    

    which means you can public_send them just as any other public method:

    1.public_send(:<=, 2)