Tarrasch
Tarrasch

Reputation: 10557

Ruby min max assignment operators

When programming ruby I always find myself doing this:

a = [a, b].min

This means compare a and b and store the smallest value in a. I don't like writing the code above as I have to write a twice.

I know that some non-standard dialects of C++ had an operator which did exactly this

a <?= b

Which I find very convenient. But I'm not really interested in the operator as much as I'm in the feature of avoiding repetition. I would also be happy if I could write

a.keep_max(b)

a can be a quite long variable, like my_array[indice1][indice2], and you don't want to write that twice.

I did alot of googling on this and found no result, hopefully this question will pop up and be useful for others aswell.

So, is there any non-repeitive way to express what I want in ruby?

Upvotes: 4

Views: 3063

Answers (4)

kentor
kentor

Reputation: 1144

def keep_max(var, other, binding)
  eval "#{var} = [#{var}, #{other}].max", binding
end

a = 5 
b = 78
keep_max(:a, :b, binding)
puts a
#=> 78

This basically does what you want. Take a look at Change variable passed in a method

Upvotes: 0

Jakub Hampl
Jakub Hampl

Reputation: 40553

What you would like to do is in fact not possible in ruby (see this question). I think the best you can do is

def max(*args)
  args.max
end

a = max a, b

Upvotes: 2

Alexandru Nedelcu
Alexandru Nedelcu

Reputation: 8069

I don't understand your question. You can always do something like this ...

module Comparable
  def keep_min(other)
     (self <=> other) <= 0 ? self : other
  end

  def keep_max(other)
     (self <=> other) >= 0 ? self : other
  end
end

1.keep_min(2)
=> 1

1.keep_max(2)
=> 2

Well, that won't work for all objects with <=> because not all of them are implementing Comparable, so you could monkey-patch Object.

Personally I prefer clarity and tend to avoid monkey-patching. Plus, this clearly is a binary predicate, just like "+", therefore method-chaining doesn't necessarily make sense so I prefer something like this to get rid of that array syntax:

def min(*args)
   args.min
end

def max(*args)
   args.max
end

min(1, 2)
=> 1

max(1, 2)
=> 2

But hey, I'm also a Python developer :-)

Upvotes: 2

Ineu
Ineu

Reputation: 1373

You can define your own method for it:

class Object
  def keep_max(other)
    [self, other].max
  end
end

a = 3
b = 7
puts a.keep_max(b)

But you should be careful defining methods on Object as it can have unpredictable behaviour (for example, if objects cannot be compared).

Upvotes: 1

Related Questions