Reputation: 5931
Is there any difference (performance? semantic? readability?) between
def test
x ? x : y
end
and
def test
x || y
end?
Also want to ask about best practices in this situation.
Upvotes: 1
Views: 261
Reputation: 1240
I prefer x || y
.
Summary: Exactly the same.
Here is my test:
ternary = ->(x, y) { x ? x : y }
ord = ->(x, y) { x || y }
puts "Ternary nil, nil: #{ternary.call(nil, nil)}"
puts "Or'd nil, nil: #{ord.call(nil, nil)}"
puts "Ternary nil, 1: #{ternary.call(nil, 1)}"
puts "Or'd nil, 1: #{ord.call(nil, 1)}"
puts "Ternary 1, nil: #{ternary.call(1, nil)}"
puts "Or'd 1, nil: #{ord.call(1, nil)}"
puts "Ternary 1, 2: #{ternary.call(1, 2)}"
puts "Or'd 1, 2: #{ord.call(1, 2)}"
The result is:
Ternary nil, nil:
Or'd nil, nil:
Ternary nil, 1: 1
Or'd nil, 1: 1
Ternary 1, nil: 1
Or'd 1, nil: 1
Ternary 1, 2: 1
Or'd 1, 2: 1
Summary: The speed differences are so negligible that if it matters, you probably shouldn't choose Ruby.
Here is my test:
require 'benchmark'
n = 10_000_000
Benchmark.bm do |b|
b.report("T n,n") { n.times do; x=nil; y=nil; x ? x : y; end }
b.report("O n,n") { n.times do; x=nil; y=nil; x || y; end }
puts
b.report("T n,1") { n.times do; x=nil; y=1; x ? x : y; end }
b.report("O n,1") { n.times do; x=nil; y=1; x || y; end }
puts
b.report("T 1,n") { n.times do; x=1; y=nil; x ? x : y; end }
b.report("O 1,n") { n.times do; x=1; y=nil; x || y; end }
puts
b.report("T 1,2") { n.times do; x=1; y=2; x ? x : y; end }
b.report("O 1,2") { n.times do; x=1; y=2; x || y; end }
end
The result is:
user system total real
T n,n 0.720000 0.000000 0.720000 ( 0.715549)
O n,n 0.780000 0.000000 0.780000 ( 0.781091)
T n,1 0.580000 0.000000 0.580000 ( 0.579195)
O n,1 0.630000 0.000000 0.630000 ( 0.636524)
T 1,n 0.580000 0.000000 0.580000 ( 0.572820)
O 1,n 0.600000 0.000000 0.600000 ( 0.599424)
T 1,2 0.580000 0.000000 0.580000 ( 0.588349)
O 1,2 0.590000 0.000000 0.590000 ( 0.587952)
Upvotes: 1
Reputation: 771
Your second example is more idiomatic to Ruby.
def test
x || y
end
It uses short circuit evaluation to return the first "truthy" value in a comparison. The performance gain between this and the ternary operator is probably negligent.
From experience, I'll say that I don't see the ternary operator very often in Ruby. One scenario where the above x || y
form won't work is when you want to select a non-empty string. In Ruby ""
is truthy, so "" || "abc"
will be true
. In this case, the ternary operator (or a regular if
statement) would work very well:
str.empty? ? "abc" : str
References:
Upvotes: 4
Reputation: 3265
Semantically, there is no difference. Both check the truthiness of x and fallback to y if x is false. The first is more readable, and is more powerful in it's usage (for example, if you want z to be returned when x is true).
In terms of performance, I ran a benchmark with 100 million iterations.
user system total real
if-else 5.480000 0.010000 5.490000 ( 5.485275)
or 5.580000 0.010000 5.590000 ( 5.597094)
The results are pretty close, there's barely any difference.
require 'benchmark'
x = false
y = 1
iterations = 100_000_000
Benchmark.bm(20) do |bm|
bm.report('if-else') do
iterations.times { z = x ? x : y }
end
bm.report('or') do
iterations.times { z = x || y }
end
end
Upvotes: 0
Reputation: 20232
I prefer the x || y
version, but it depends on what x
and y
are. I find it more readable as you don't have to repeat the x
.
as for faster a quick and dirty benchmark shows there is not much (if any differnce)
require 'benchmark'
n=1_000_000
Benchmark.bm do |b|
b.report("||") { n.times do ; x=true; y=2; x || y; end }
b.report("? :") { n.times do ; x=true; y=2; x ? x :y ; end }
end
run 1
[~] ruby foo.rb
user system total real
|| 0.080000 0.000000 0.080000 ( 0.076901)
? : 0.080000 0.000000 0.080000 ( 0.076868)
run 2
[~] ruby foo.rb
user system total real
|| 0.070000 0.000000 0.070000 ( 0.076943)
? : 0.080000 0.000000 0.080000 ( 0.077277)
run 3
[~] ruby foo.rb
user system total real
|| 0.070000 0.000000 0.070000 ( 0.075403)
? : 0.080000 0.000000 0.080000 ( 0.076831)
[~] ruby -v
ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-darwin13.0]
Upvotes: 3