I consider the following statements to be perfectly legit (although
perhaps slightly ambigious) and Ruby does obey, but throws this
mandating warning. Am I just being paranoid or is Ruby forcing a style
upon me :)?
irb(main):008:0> if a = 1 then true else false end
(irb):8: warning: found = in conditional, should be ==
=> true
irb(main):009:0> a
=> 1
irb(main):010:0> if a = nil then true else false end
(irb):10: warning: found = in conditional, should be ==
=> false
irb(main):011:0> a
=> nil
I consider the following statements to be perfectly legit (although
perhaps slightly ambigious) and Ruby does obey, but throws this
mandating warning. Am I just being paranoid or is Ruby forcing a style
upon me :)?
A single equals sign does assignment, so a statement like:
if a = 1 then true else false end
assigns the value 1 to ‘a’, and then evaluates the “truthfulness” of
‘a’. In Ruby, only ‘false’ and and ‘nil’ evaluate to false, so this
statement will always evaluate to true (i.e. because ‘a’ is 1, and 1
is true).
If you’re wanting to check whether the current value of ‘a’ is 1, you
need to use two equals signs instead, i.e.
if a == 1 then true else false end
This statement doesn’t change the value of ‘a’ (as the previous
statement did). It just compares its current value against another value
(1) and returns true if they are equal.
Apologies in advance if you already understand this distinction, but it
is one that has tripped many a programmer, even those who should know
better If you indeed mean to assign the value to ‘a’ (as in the first
example), you can probably avoid the warning from Ruby by breaking this
into two lines, e.g.
I consider the following statements to be perfectly legit (although
perhaps slightly ambigious) and Ruby does obey, but throws this
mandating warning. Am I just being paranoid or is Ruby forcing a style
upon me :)?
It is. The ‘gcc’ style… an additional pair of parens around the
expression et voila (funny enough, you need two)
irb(main):001:0> if a = 1 then true else false end
(irb):1: warning: found = in conditional, should be ==
=> true
irb(main):002:0> if (a=1) then true else false end
(irb):2: warning: found = in conditional, should be ==
=> true
irb(main):003:0> if ((a=1)) then true else false end
=> true
Regards,
-Martin
…to which David replied:
It is. The ‘gcc’ style… an additional pair of parens around the
expression et voila (funny enough, you need two)
Pretty interesting. Anyone has the full story on why?
/ David
Sorry.
-Martin
···
On Wed, Jan 14, 2004 at 02:40:16AM +0900, David Heinemeier Hansson wrote:
Date: Wed, 14 Jan 2004 02:40:16 +0900
From: David Heinemeier Hansson david@loudthinking.com
Newsgroups: comp.lang.ruby
Subject: Warnings on assignments in conditionals?
I consider the following statements to be perfectly legit (although
perhaps slightly ambigious) and Ruby does obey, but throws this
mandating warning. Am I just being paranoid or is Ruby forcing a style
upon me :)?
irb(main):008:0> if a = 1 then true else false end
irb(main):008:0> if((a = 1)) then true else false end
(irb):8: warning: found = in conditional, should be ==
=> true
irb(main):009:0> a
=> 1
irb(main):010:0> if a = nil then true else false end
irb(main):010:0> if((a = nil)) then true else false end
(irb):10: warning: found = in conditional, should be ==
=> false
irb(main):011:0> a
=> nil
The difference between art and science is that science is what we
understand well enough to explain to a computer.
Art is everything else.
– Donald Knuth, “Discover”
/bin/sh -c ‘for l in ruby perl;do $l -e “print "\x3a\x2d\x29\x0a"”;done’
===============================================================================
I consider the following statements to be perfectly legit (although
perhaps slightly ambigious) and Ruby does obey, but throws this
mandating warning. Am I just being paranoid or is Ruby forcing a style
upon me :)?
irb(main):008:0> if a = 1 then true else false end
(irb):8: warning: found = in conditional, should be ==
=> true
irb(main):009:0> a
=> 1
irb(main):010:0> if a = nil then true else false end
(irb):10: warning: found = in conditional, should be ==
=> false
irb(main):011:0> a
=> nil
But this C idiom really doesn’t make much sense in Ruby, since
in Ruby 0 is true in a boolean context. You might want to say
something like:
if not (a = c).nil? then foo else bar end
but what you have is almost certainly either an error or at least
stylistically dubious. So yes, I guess Ruby is forcing a style on
you. I think that if you really want something like this, the Ruby
way would be to define a method ‘true?’ for objects:
class Object
def true?
if nil? or self == false then return false end
true
end
def false?
not true?
end
end
then write:
if (a = c).true? then foo else bar end
I consider the following statements to be perfectly legit (although
perhaps slightly ambigious) and Ruby does obey, but throws this
mandating warning. Am I just being paranoid or is Ruby forcing a style
upon me :)?
irb(main):008:0> if a = 1 then true else false end
(irb):8: warning: found = in conditional, should be ==
=> true
irb(main):009:0> a
=> 1
irb(main):010:0> if a = nil then true else false end
(irb):10: warning: found = in conditional, should be ==
=> false
irb(main):011:0> a
=> nil
Just a side remark: assignment in conditional is only used in loops. “if”
never needs this. You can always put it onto two lines even gaining
readability:
I consider the following statements to be perfectly legit (although
perhaps slightly ambigious) and Ruby does obey, but throws this
mandating warning. Am I just being paranoid or is Ruby forcing a style
upon me :)?
irb(main):008:0> if a = 1 then true else false end
(irb):8: warning: found = in conditional, should be ==
=> true
irb(main):009:0> a
=> 1
irb(main):010:0> if a = nil then true else false end
(irb):10: warning: found = in conditional, should be ==
=> false
irb(main):011:0> a
=> nil
But this C idiom really doesn’t make much sense in Ruby, since
in Ruby 0 is true in a boolean context. You might want to say
something like:
if not (a = c).nil? then foo else bar end
but what you have is almost certainly either an error or at least
stylistically dubious. So yes, I guess Ruby is forcing a style on
you. I think that if you really want something like this, the Ruby
way would be to define a method ‘true?’ for objects:
class Object
def true?
if nil? or self == false then return false end
true
end
def false?
not true?
end
end
then write:
if (a = c).true? then foo else bar end
shudder You’re not serious, are you? And if so, why didn’t you define
them like this:
class Object
def true?; self; end
def false?; not self; end
end