Will
Will

Reputation: 2808

Most elegant way to add 1 to an integer if a boolean is true in Ruby?

This will be an easy question for you Ruby experts: What is the most elegant way to add the value of 1 to an integer if a boolean is true?

For example, extra_unit is a boolean, and I want to add 1 to the total only if extra_unit is true.

total = unit_price * (units + (extra_unit ? 1 : 0 ))

Is that the most elegant solution, where, by "elegant", I mean in terms of compact but still readable code?

Upvotes: 0

Views: 544

Answers (1)

the Tin Man
the Tin Man

Reputation: 160549

Given the caveat in my comment to the question above, and if I wanted it on one line and didn't care what it did to the mind of a coworker or my future self, I'd do something like this:

total = unit_price * (bonus ? units + 1 : units)

But, really, it could be written more verbosely without affecting the speed, which would increase the readability:

unit_price = 1.00
units = 1
bonus = true

unit_price * (units + (bonus ? 1 : 0 )) # => 2.0
unit_price * (bonus ? units + 1 : units) # => 2.0
multiplier = if bonus
              units + 1
            else
              units
            end
unit_price * multiplier # => 2.0

Those all return the same value so they're equivalent in result.

Running some benchmarks:

require 'fruity'
compare do
  t1 {unit_price * (units + (bonus ? 1 : 0 ))}
  t2 {unit_price * (bonus ? units + 1 : units)}
  t3 {
    multiplier = if bonus
                  units + 1
                else
                  units
                end
    unit_price * multiplier
  }
end

# >> Running each test 65536 times. Test will take about 2 seconds.
# >> t2 is similar to t1
# >> t1 is similar to t3

I ran the benchmarks multiple times, and the positions would swap, with t3 being marginally slower twice, but not enough that Fruity would consistently flag it as such.

So, as far as elegance goes, insisting that it being cryptic or as small as possible doesn't necessarily buy us anything useful, so instead go with readable and still fast. From experience, benchmarks are essential if you're going for elegant; Too often I've been surprised when I thought something would be faster because it was concise, when in comparison another more verbose expression ran circles around it.

Upvotes: 3

Related Questions