Ruby's "foo = true if !defined? foo" won't work as expected
When it is in fact not defined, it gets the value nil
just because it was "touched":
$ irb
ruby-1.9.2-p0 > foo = true if !defined? foo
=> nil
ruby-1.9.2-p0 > foo
=> nil
ruby-1.9.2-p0 > if !defined? bar
ruby-1.9.2-p0 ?> bar = true
ruby-1.9.2-p0 ?> end
=> true
ruby-1.9.2-p0 > bar
=> true
so 开发者_运维知识库the if
... end
works as expected, but foo = true if ...
doesn't.
Ruby defines a local variable just before executing a line containing an assignment, so defined?(foo)
will always be true
for the one-liner.
Another example showing that local variables are defined before any part of the line are executed:
defined? foo # => false
foo = foo # => foo is now nil
it does sound reasonable that [statement] if [expression]
is just rearranged by the compiler to
if [expression] then [statement] end
but it looks like it's handled specially in a way which breaks defined? actually, defined looks like a special construct (i.e. not a normal function)
looks like if your assigning it in the same line you should check for .nil? instead:
foo = foo.nil? ? true : foo
(this also works if it's already set to false)
The way to think about this is:
foo = (true if !defined? foo)
So, first foo is defined, then the expression to give it a value is run.
精彩评论