Does it? Foo = is the expression legal in Ruby?
Note. I'm not really sure what to name the question, so if anyone understands better please edit it.
I will go straight to the question as no explanation is required.
This code:
!foo = true
generates this warning
warning: found = in conditional, should be ==
I would understand if this happened after the instruction if
or unless
, but it couldn't be further from them (exaggeration). I understand that I can use:
foo = true !foo
I suppose the warning doesn't really matter, but it's a little annoying that Ruby assumes I'm doing something wrong and when I'm not.
Questions:
- This is mistake?
- Can the warning be turned off?
Thank!
source to share
Is legal. Not a mistake. The warning can be suppressed.
You can turn off the warning:
$VERBOSE = nil
Interestingly, this $VERBOSE
is the case where setting something for false
does something other than setting it on nil
.
By the way, the other answers, at least initially, tend to suggest that Ruby parses an expression as
(!foo) = true
... but it isn't. It is parsed as:
!(foo = true)
... and so it does exactly what the OP wanted. And there is no specification or ratified standard for Ruby, so if it works in MRI (reference implementation) then it is legal.
source to share
As the previous answers have said, this is not really what you are doing.
!foo = true
assessed as
!(foo = true)
That is, assign true
foo
and get the negation of the result of that assignment, which boils down to
!true
or
false
If you want to keep !true
it should be
foo = !true
If you want to assign true to foo and negate another variable, that would be
foo2 = !(foo = true)
and that will still raise a warning, because after all, it's a conditional assignment.
I really want to assign true to foo and then get the opposite foo on the stack
Doesn't make much sense. You "get something on the stack" by assigning it to a variable, like foo2
in my example.
If the goal here is to assign an instance variable and return the negation from the method, then yes, you will have to assign the variable first and then explicitly return the negation. This is not a bug in Ruby, but actually a function, and for clean code, you shouldn't do it on one line, because it's basically indistinguishable from a common usage error =
when it comes to ==
.
source to share
This is just a warning and evaluates as you expect. You can temporarily disable warnings by assigning $ VERBOSE = nil.
save_verbose, $VERBOSE = $VERBOSE, nil
result = !foo = true
$VERBOSE = save_verbos
result
Other places on the net , suggest making a helper method ala
module Kernel
def silence_warnings
with_warnings(nil) { yield }
end
def with_warnings(flag)
old_verbose, $VERBOSE = $VERBOSE, flag
yield
ensure
$VERBOSE = old_verbose
end
end unless Kernel.respond_to? :silence_warnings
But I just tried this in 1.9.2 and 1.8.7 and it was ineffective for suppressing the "warning: found = in conditional, must be =="
source to share