Set Ruby variable if it is not already defined

2019-01-22 12:03发布

问题:

In Ruby, how do you set a variable to a certain value if it is not already defined, and leave the current value if it is already defined?

回答1:

While x ||= value is a way to say "if x contains a falsey value, including nil (which is implicit in this construct if x is not defined because it appears on the left hand side of the assignment), assign value to x", it does just that.

It is roughly equivalent to the following. (However, x ||= value will not throw a NameError like this code may and it will always assign a value to x as this code does not -- the point is to see x ||= value works the same for any falsey value in x, including the "default" nil value):

if !x
  x = value
end  

To see if the variable has truly not been assigned a value, use the defined? method:

>> defined? z
=> nil                                                                  
>> z = nil                                                              
=> nil                                                                  
>> defined? z                                                           
=> "local-variable"                                                     
>> defined? @z                                                          
=> nil                                                                  
>> @z = nil                                                             
=> nil                                                                  
>> defined? @z                                                          
=> "instance-variable" 

However, in almost every case, using defined? is code smell. Be careful with power. Do the sensible thing: give variables values before trying to use them :)

Happy coding.



回答2:

@variable ||= "set value if not set"

So false variables will get overridden

> @test = true 
 => true 
> @test ||= "test"
 => true 
> @test 
 => nil 
> @test ||= "test"
 => "test" 
> @test = false 
 => false 
> @test ||= "test"
 => "test" 


回答3:

As you didn't specify what kind of variable:

v = v
v ||= 1

Don't recommend doing this with local variables though.

Edit: In fact v=v is not needed



回答4:

A bit late but a working solution that also does not overwrite falsey values (including nil):

# assuming x is not defined in current scope
!defined?(x) ? x = 42 : nil  # => x == 42

y = false
!defined(y) ? y = 42 : nil   # => x == false

z = nil
!defined(z) ? z = 42 : nil   # => z == nil


回答5:

If the variable is not defined (declared?) it doesn't exist, and if it is declared then you know how you initialized it, right?

Usually, if I just need a variable whose use I don't yet know---that I know will never use as a Boolean---I initialize it by setting its value to nil. Then you can test if it has been changed later quite easily

x = nil


some code


if x do 
[code that will only run if x has changed]
end

that's all.