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):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

···


David Heinemeier Hansson.
http://www.loudthinking.com/ – Broadcasting Brain

David Heinemeier Hansson wrote:

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 :wink: 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.

 a = 1
 if a then true else false end

Hope this helps,

Lyle

Oops, accidentally replied in private:

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

David Heinemeier Hansson.
http://www.loudthinking.com/ – Broadcasting Brain

-a

···

On Wed, 14 Jan 2004, David Heinemeier Hansson wrote:

ATTN: please update your address books with address below!

===============================================================================

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
STP :: Solar-Terrestrial Physics Data | NCEI
NGDC :: http://www.ngdc.noaa.gov/
NESDIS :: http://www.nesdis.noaa.gov/
NOAA :: http://www.noaa.gov/
US DOC :: http://www.commerce.gov/

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’
===============================================================================

David Heinemeier Hansson david@loudthinking.com wrote in message news:8609BD15-45EF-11D8-A416-000A958E6254@loudthinking.com

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

Oinkful Regards, Bret

“David Heinemeier Hansson” david@loudthinking.com schrieb im Newsbeitrag
news:8609BD15-45EF-11D8-A416-000A958E6254@loudthinking.com

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:

a = 1
if a then …

Besides of that you can do

a = 1 and …

This will look familiar to P*rl users.

You only really need it in situations like this:

while ( line = gets )

end

Cheers

robert

“Bret Jolly” oinkoink+unet@rexx.com schrieb im Newsbeitrag
news:7e7131a1.0401141110.d5fa65a@posting.google.com

David Heinemeier Hansson david@loudthinking.com wrote in message
news:8609BD15-45EF-11D8-A416-000A958E6254@loudthinking.com

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

Cheers

robert

“Robert Klemme” bob.news@gmx.net wrote in message news:bu5l86$dmuo3$1@ID-52924.news.uni-berlin.de

“Bret Jolly” oinkoink+unet@rexx.com schrieb im Newsbeitrag
[stuff]

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

Yes, that’s much better.
Oinkful and Blushing Regards, Bret