x==1 vs 1==x

G

Gavin Kistner

--Apple-Mail-1--767860423
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
charset=US-ASCII;
delsp=yes;
format=flowed

I'm against _premature_ optimization in theory, but believe that a
certain innate knowledge of what is and what is not efficient is
important for making reasonable choices in the first place.

To that end, when I had to write code to handle exactly one case out
of many, where I knew that the operator would be #==, I thought I'd
test case versus if/elsif. As I expected, the case statement
performed worse (thought not as much as I expected).

On a whim, I also tested comparing x == 1 separate from 1 == x. Even
when x was a Fixnum, the latter was surprisingly and significantly
slower. Can anyone explain the following results?

8
Fixnum
Rehearsal ---------------------------------------------
case 1.500000 0.020000 1.520000 ( 2.249505)
if x==n 0.930000 0.020000 0.950000 ( 1.332420)
if n==x 1.330000 0.020000 1.350000 ( 1.914666)
------------------------------------ total: 3.820000sec

user system total real
case 1.510000 0.020000 1.530000 ( 2.343995)
if x==n 0.920000 0.020000 0.940000 ( 1.277303)
if n==x 1.340000 0.020000 1.360000 ( 1.937022)


require 'benchmark'

n = 100_000
x = rand( 10 )
p x, x.class
Benchmark.bmbm(10){ |x|
x.report('case'){
n.times{
case x
when 0 : 0
when 1 : 1
when 2 : 2
when 3 : 3
when 4 : 4
when 5 : 5
when 6 : 6
when 7 : 7
when 8 : 8
else 9
end
}
}
x.report('if x==n'){
n.times{
if x==0
0
elsif x==1
1
elsif x==2
2
elsif x==3
3
elsif x==4
4
elsif x==5
5
elsif x==6
6
elsif x==7
7
elsif x==8
8
else
9
end
}
}

x.report('if n==x'){
n.times{
if 0==x
0
elsif 1==x
1
elsif 2==x
2
elsif 3==x
3
elsif 4==x
4
elsif 5==x
5
elsif 6==x
6
elsif 7==x
7
elsif 8==x
8
else
9
end
}
}
}
 
R

Robert Klemme

Gavin said:
I'm against _premature_ optimization in theory, but believe that a
certain innate knowledge of what is and what is not efficient is
important for making reasonable choices in the first place.

To that end, when I had to write code to handle exactly one case out
of many, where I knew that the operator would be #==, I thought I'd
test case versus if/elsif. As I expected, the case statement
performed worse (thought not as much as I expected).

On a whim, I also tested comparing x == 1 separate from 1 == x. Even
when x was a Fixnum, the latter was surprisingly and significantly
slower. Can anyone explain the following results?

Yes, probably: you have something else in x than you expect. x is really
the benchmark instance and not some Fixnum. :)

Kind regards

robert
 
T

ts

G> p x, x.class

uln% diff -u b.rb~ b.rb
--- b.rb~ 2005-06-20 15:16:51.990598152 +0200
+++ b.rb 2005-06-20 15:17:40.826174016 +0200
@@ -3,8 +3,8 @@
n = 100_000
x = rand( 10 )
p x, x.class
-Benchmark.bmbm(10){ |x|
- x.report('case'){
+Benchmark.bmbm(10){ |xx|
+ xx.report('case'){
n.times{
case x
when 0 : 0
@@ -20,7 +20,7 @@
end
}
}
- x.report('if x==n'){
+ xx.report('if x==n'){
n.times{
if x==0
0
@@ -46,7 +46,7 @@
}
}

- x.report('if n==x'){
+ xx.report('if n==x'){
n.times{
if 0==x
0
uln%

uln% ruby b.rb
7
Fixnum
Rehearsal ---------------------------------------------
case 0.170000 0.000000 0.170000 ( 0.179179)
if x==n 0.190000 0.010000 0.200000 ( 0.194086)
if n==x 0.190000 0.000000 0.190000 ( 0.191561)
------------------------------------ total: 0.560000sec

user system total real
case 0.160000 0.020000 0.180000 ( 0.180628)
if x==n 0.190000 0.010000 0.200000 ( 0.195471)
if n==x 0.190000 0.010000 0.200000 ( 0.193239)
uln%



Guy Decoux
 
G

Gavin Kistner

--Apple-Mail-2--766872557
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
charset=US-ASCII;
format=flowed

-Benchmark.bmbm(10){ |x|
+Benchmark.bmbm(10){ |xx|

rofl

Oops. Thanks :)
--Apple-Mail-2--766872557--
 
J

Jason Foreman

=20
rofl
=20
Oops. Thanks :)
=20

Even though it turns out there is no performance benefit to 1 =3D=3D x
over x =3D=3D 1, I find it desirable to write the former anyway. If you
accidentally write x =3D 1 instead of x =3D=3D 1, it can take a long time t=
o
figure out your bug. But if you write 1 =3D x instead of 1 =3D=3D x, you
get a syntax error, and can immediately correct the mistake.


Jason
 
P

Peter Hickman

Jason said:
Even though it turns out there is no performance benefit to 1 == x
over x == 1, I find it desirable to write the former anyway. If you
accidentally write x = 1 instead of x == 1, it can take a long time to
figure out your bug. But if you write 1 = x instead of 1 == x, you
get a syntax error, and can immediately correct the mistake.

Jason
Although I can see a that writing 1 == x makes to catch 1 = x errors
makes a lot of sense it just doesn't read correctly to me. After all it
is the variable (reference) x that we are talking about, I would expect
to see it to be more prominently in the sentence, so to speak.

Just as I would prefer to read 1 <= x and x <= 100 over 1 <= x and 100 >
x. But then again I would prefer the icon idiom of 1 <= x <= 100.

I wonder if this relates to the grammar of your natural language (with
the subject, object, verb ordering).
 
F

Florian Groß

Jason said:
If you accidentally write x = 1 instead of x == 1, it can take a long
time to figure out your bug.

C:\Dokumente und Einstellungen\flgr>ruby
foo = 10
if foo = 10 then
puts "Hello World!"
end
-:2: warning: found = in conditional, should be ==
^Z
Hello World!

I found out about my bug before I was even done giving Ruby the full
application code. ;)
 
N

Nikolai Weibull

Jason said:
Even though it turns out there is no performance benefit to 1 == x
over x == 1, I find it desirable to write the former anyway. If you
accidentally write x = 1 instead of x == 1, it can take a long time to
figure out your bug. But if you write 1 = x instead of 1 == x, you
get a syntax error, and can immediately correct the mistake.

% ruby
if x = 1; end
-:1: warning: found = in conditional, should be ==

So please don't write your code as if it was 1980 and you were using a C
compiler,
nikolai
 
J

Jason Foreman

Jason Foreman wrote:
=20
=20
C:\Dokumente und Einstellungen\flgr>ruby
foo =3D 10
if foo =3D 10 then
puts "Hello World!"
end
-:2: warning: found =3D in conditional, should be =3D=3D
^Z
Hello World!
=20
I found out about my bug before I was even done giving Ruby the full
application code. ;)
=20
=20
=20

Nice. I didn't realize it gave that warning! :)

However:

$ ruby
x=3D2
case x
when x=3D1: p 'one'
when x=3D=3D2: p 'two'
else p 'whoops!'
end
^D
"whoops!"
 
M

Michael Campbell

Jason Foreman wrote:
=20
=20
% ruby
if x =3D 1; end
-:1: warning: found =3D in conditional, should be =3D=3D
=20
So please don't write your code as if it was 1980 and you were using a C
compiler,
nikolai

Amen. Even C compilers catch this sort of thing now; there's no need
for this logic-bending construct anymore.
 
R

Robert Klemme

Jason said:
Nice. I didn't realize it gave that warning! :)

However:

$ ruby
x=2
case x
when x=1: p 'one'
when x==2: p 'two'
else p 'whoops!'
end
^D
"whoops!"

Do you suggest to add a warning if there is an expression after "case"
*and* at least a single boolean expression after "when"? Note that the
correct form of what you did is this:

x=2
case
when x==1: p 'one'
when x==2: p 'two'
else p 'whoops!'
end

Kind regards

robert
 
J

Jason Foreman

Jason Foreman wrote:
=20
=20
% ruby
if x =3D 1; end
-:1: warning: found =3D in conditional, should be =3D=3D
=20
So please don't write your code as if it was 1980 and you were using a C
compiler,
nikolai
=20

You're right, this type of coding went out of style about the same
time as little code snippet sigs...

Oh wait...

;)


All personal attacks aside, Ruby does not issue warnings for this type
of error in all cases (pun intended, see my last message for example)

I happen to like to write my code a certain way, but if you don't
prefer it that's fine with me.


Jason
 
J

Jason Foreman

=20
Do you suggest to add a warning if there is an expression after "case"
*and* at least a single boolean expression after "when"? Note that the
correct form of what you did is this:
=20
x=3D2
case
when x=3D=3D1: p 'one'
when x=3D=3D2: p 'two'
else p 'whoops!'
end
=20
Kind regards
=20
robert
=20
=20
=20

Right, I should have used "case" and not "case x". Thanks for
pointing this out.

The corrected example of the problem I was trying to demonstrate is:
$ ruby
x=3D2
case
when x=3D1: p 'one'
when x=3D=3D2: p 'two'
end
^D
"one"


I'm not so sure you could easily add a warning for this, without
crippling some of the capabilities of the language. Someone may very
well want to do an assignment there. The probability of someone
writing a case expression like that are probably very low though.

It comes down to the fact that I like to write 1=3D=3Dx, because I made
too many x=3D1 vs x=3D=3D1 type of errors when I was learning to program an=
d
now its habit. Nobody else seems to agree with me though, so whatever
:)


Jason
 
J

James Edward Gray II

All personal attacks aside, Ruby does not issue warnings for this type
of error in all cases (pun intended, see my last message for example)

That's probably because there are some valid uses for it:

if error = messages.find { |mess| mess.error? }
# ...
end

If memory serves, Ruby doesn't whine about the above and that makes
me very happy.

James Edward Gray II
 
B

Ben Giddings

% ruby
if x = 1; end
-:1: warning: found = in conditional, should be ==

So please don't write your code as if it was 1980 and you were using a C
compiler,

def retrieve_good_status_val
:good_status
end

def retrieve_bad_status_val
:bad_status
end

def get_status(good, bad)
if rand > 0.2
good
else
bad
end
end

good_status = retrieve_good_status_val
bad_status = retrieve_bad_status_val
while good_status = get_status(good_status, bad_status)
puts "Still good"
sleep 0.1
end
puts "Bad status"

Ruby can get the simple cases like 'if x = 1' but it can't get all the
variations.

At first, it might look ugly to have the un-assignable operand first, but
you get used to it quickly, and a bit of ugliness is a small price to pay
for more robust programs.

I write for C compilers all the time, but when I write Ruby there are still
a lot of things I keep, even with its smarter interpreter. In the end, I
think using '=' as the assignment operator and '==' as the comparison
operator is bad human-interface design. What do you call that key?
"equals", not "assigns" or something, but it's hardly a flaw unique to
Ruby. :)

Ben
 
S

Sebastian Biallas

Ben Giddings wrote:

def retrieve_good_status_val
:good_status
end

def retrieve_bad_status_val
:bad_status
end

def get_status(good, bad)
if rand > 0.2
good
else
bad
end
end

good_status = retrieve_good_status_val
bad_status = retrieve_bad_status_val
while good_status = get_status(good_status, bad_status)

I guess you mean you would write this as
while get_status(good_status, bad_status) = good_status
so that ruby could detect the problem...

But what if this was written as
good_status = retrieve_good_status_val
bad_status = retrieve_bad_status_val
status = get_status(good_status, bad_status)
while status = good_status

?
puts "Still good"
sleep 0.1
end
puts "Bad status"

Ruby can get the simple cases like 'if x = 1' but it can't get all the
variations.

And you can't write all cases backwards. It's better to be always very
careful with '=' vs. '==' instead of missing the really nasty cases
because "my syntax is safe[tm]"
At first, it might look ugly to have the un-assignable operand first, but
you get used to it quickly, and a bit of ugliness is a small price to pay
for more robust programs.

Since you have to test your programs in either case (especially with
ruby since a lot of errors are only detected at runtime) I don't see why
programs get more robust.

On the contrary, your programs become harder to read and piss off a lot
of codevelopers (well, at least me ;) )
I write for C compilers all the time, but when I write Ruby there are still
a lot of things I keep, even with its smarter interpreter. In the end, I
think using '=' as the assignment operator and '==' as the comparison
operator is bad human-interface design. What do you call that key?
"equals", not "assigns" or something, but it's hardly a flaw unique to
Ruby. :)

Well, you are somewhat correct here. I, for one, would prefer a ":=" or
"<-" operator as assignment. But with current ruby syntax it is better
to use an editor/font which clearly distinguishes between '=' and '=='
so that such errors are highly unlikely.

Sebastian
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top