Why does:
something = false
always return false?
Since it is an assignment and not a comparison, it seems it would make more sense to return the result (success/failure) of the assignment (like pretty much every other assignment you do).
EDIT - this is wrong, as the answers below point out. My bad. Slight brain fart. See the original impetus for this question in the comments below.
What happens if some_boolean_var = false
failed for whatever reason (unlikely, but theoretically possible, especially if you defined a custom method for this action)? That would also return false, so you have no indication as to whether the assignment actually worked.
It basically just means you can't combine assignment and comparison in one line like you can do with nearly everything else in Rails. For example, you can't do:
if something = false (note the single =)
do stuff
end
I mean you can do it but not if you wanted to check and make sure the assignment succeeded first.
Just really weird to me.
I'm sure there is a reason for this so please enlighten me :)
Thanks in advance!
2 Answers 2
In ruby (and may languages that trace some semblance of a lineage to C), the =
operator traditionally returns the value that was assigned.
>> foo = false
=> false
>> foo = 4
=> 4
This allows one to use what is known as chained assignment (see related question on P.SE) to do things such as:
>> foo = bar = 42
=> 42
>> foo
=> 42
>> bar
=> 42
In this example, it is parsed as foo = (bar = 42)
. From this, bar = 42
returns 42
, which is then assigned to foo
.
This type of structure is found in C, C++, Java, Perl and many other languages.
Think of it this way - every operator returns something - what else would =
return than the value that was assigned?
While it doesn't allow your if something = false
test, it does allow for structures that resumable:
while data = file.getc
...
end
In Ruby getc
returns the character read (and an nil (a falsey value) when the file has been completely read). Thus, the read and the loop conditional test are done within the loop itself.
-
Ahh, so it isn't that those other statements return true, it is that the values they return just happen to evaluate to true when compared. Gotcha. I guess that is fairly obvious now that I think about it. I just got burned recently because I was setting an attribute to false in the last line of a before_save callback. 4 hours later and I figured out why my records weren't saving :)bcb– bcb2013年10月12日 19:26:56 +00:00Commented Oct 12, 2013 at 19:26
-
@bcb in Ruby,
nil
andfalse
are false. Everything else is true.user40980– user409802013年10月12日 19:29:53 +00:00Commented Oct 12, 2013 at 19:29 -
The sad thing is I have a Computer Science degree from Georgia Tech and nearly 20 years of experience, and this little problem was driving me nuts. It is always the little things . . .bcb– bcb2013年10月12日 19:31:06 +00:00Commented Oct 12, 2013 at 19:31
-
@MichaelIT . . . that fact was not lost on me, for some reason I had glossed over the fact that assignments return the value of the assignment, not true or false. That is now truly obvious (otherwise something = 5 would result in nothing happening) and I apologize for wasting everyone's time. Carry on, nothing to see here :) Seriously though, thanks for clarifying this for me. If someone wants to take something truly useful away from this, be careful putting any kind of assignment to false at the end of your callbacks, unless you really want to halt the callback chain :)bcb– bcb2013年10月12日 19:36:57 +00:00Commented Oct 12, 2013 at 19:36
-
No problem at all - realize that someone else some day may have the same question (you didn't waste time) and will now be able to find it on P.SE. The questions are the seeds of the slowly growing knowledge base that is Stack Exchange.user40980– user409802013年10月12日 19:39:17 +00:00Commented Oct 12, 2013 at 19:39
Assignment evaluates to the assigned value, which can be useful for some shortcuts, e.g:
if x = get_some_value()
puts "x is #{x}"
else
puts "no x"
end