Reputation: 2808
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
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