This question already has answers here:
Undefine variable in Ruby
(5 answers)
Closed 9 years ago.
I want to destroy a variable in ruby as if it had never existed. Here is an example:
> defined? a
=> "nil"
> a = 1
> defined? a
=> "local-variable"
Now I need to set variable a to "nil" when I do defined?.
I tried some things like:
> a = nil #Not working
=> nil
> defined? a
=> "local-variable"
But nothing seems to work.
As of now (MRI 2.2 and before), there's no way to do this.
Related
This question already has answers here:
Why can I refer to a variable outside of an if/unless/case statement that never ran?
(3 answers)
Closed 5 years ago.
Recently I found out that a non-evaluated line, in Ruby, still assigns nil to the variable.
2.3.4 (main):0 > defined? this_never_seen_variable_before
=> nil
2.3.4 (main):0 > this_never_seen_variable_before = "value" if false
=> nil
2.3.4 (main):0 > defined? this_never_seen_variable_before
=> "local-variable"
2.3.4 (main):0 >
2.3.4 (main):0 > this_never_seen_variable_before_2
NameError: undefined local variable or method `this_never_seen_variable_before_2' for main:Object
from (pry):119:in `<main>'
2.3.4 (main):0 > this_never_seen_variable_before_2 = "value" if false
=> nil
2.3.4 (main):0 > this_never_seen_variable_before_2
=> nil
2.3.4 (main):0 >
Would anyone have more information about it?
Before your Ruby code can be run, it must first be parsed, and it's at this stage that the behavior you're experiencing originates.
As the parser scans through the code, whenever it encounters a declaration (foo = 'something') it allocates space for that variable by setting its value to nil. Whether that variable declaration is actually executed in the context of your code is irrelevant. For example:
if false
foo = 42
end
p foo
#=> nil
In the above code's logic foo is never declared, however it's space in memory is recognized and allocated for by Ruby when the code is parsed out.
Hope this helps!
This question already has answers here:
What does ||= (or-equals) mean in Ruby?
(23 answers)
Closed 7 years ago.
I'm still pretty green when it comes to Ruby and am trying to figure out what this is doing:
command_windows.each {|window| window.hidden ||= window.open? }
The command_windows variable appears to be an array of objects. If someone could explain to me what this line of code means, particularly what the ||= symbol is I would appreciate it.
foo ||= "bar" is the equivalent of doing foo || foo = "bar".
As Mischa explained, it checks for a falsy value before assigning.
In your case, you could think of it as:
command_windows.each {|window| window.hidden || window.hidden = window.open? }
which is another way of saying
command_windows.each {|window| window.hidden = window.open? unless window.hidden }
The ||= operator is used to assign new value to variable. If something was assigned to it before it won't work. It is usually used in hashes, so you don't have to check, if something is already assigned.
This question already has answers here:
Confusion with the assignment operation inside a falsy `if` block [duplicate]
(3 answers)
Closed 5 years ago.
Try the following in irb: (I'm using Ruby 2.0.0-p247)
blah
#=> NameError: undefined local variable or method `blah' for main:Object
if false
blah = 'blah'
end
#=> nil
blah
#=> nil
I'm surprised that blah is assigned nil even when the if condition evaluates to false.
I thought the code within if is skipped as the condition evaluates to false.
Could someone with Ruby internals knowledge kindly explain how this happened?
Thank you
Local variables in ruby are created during parsing/compilation of code (not execution). They are lexically scoped, so a local variable is not visible before the line where it's assigned to.
defined?(foo) # => nil
if false
defined?(foo) # =>
foo = 'blah'
defined?(foo) # =>
end
defined?(foo) # => "local-variable"
foo # => nil
defined?(foo) lines inside of if return nothing, because they didn't run. The assignment wasn't executed as well. However, the compiler saw the assignment to local variable and created one (with default value of nil).
This behaviour explains the trick from WAT talk:
a = a # => nil
Even though variable a doesn't exist, it is created (and set to nil) right before this line, simply because there is an assignment expression in the code (target of which is yet unknown local variable). So by the time the right hand side of this expression is evaluated, a exists.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
What does ||= mean in Ruby?
I tested like this:
>> a||=3
=> 3
>> a
=> 3
>> a||=b
=> 3
>> b
NameError: undefined local variable or method `b' for main:Object
from (irb):11
It is the shorthand for a logical OR operation. It is equivalent to:
a || a = b
Note: The above code sample has been corrected to reflect the true (if unintuitive) behavior if expanding a ||= b. Thanks to the people who pointed that out for me. Here is the source
if a evaluates to true it will remain as is, otherwise b will be assigned to a. In ruby nil evaluates to false, so you can see how this is useful for lazy loading and default value assignment.
This question already has answers here:
How to call methods dynamically based on their name? [duplicate]
(5 answers)
Closed 8 years ago.
Regardless of whether it's good practice or not, how can I dynamically call accessor methods in Ruby?
Here's an example class:
class Test_Class
attr_accessor :a, :b
end
I can use the Object.send method to read the variable...
instance.a = "value"
puts( instance.send( "a" ) )
# => value
But I'm having a hard time trying to write to it. These throw "wrong number of arguments (1 for 0) (ArgumentError)"
instance.send("a", "value")
and
instance.method("a").call("value")
Please help me StackOverflow!
I am not a ruby expert, but I think that you could do:
instance.send("a=", "value")
You can also directly access instance variables of an object using instance_variable_* functions:
instance = Test_Class.new # => #<Test_Class:0x12b3b84>
# instance variables are lazily created after first use of setter,
# so for now instance variables list is empty:
instance.instance_variables # => []
instance.instance_variable_set(:#a, 123) # => 123
instance.a # => 123
instance.instance_variables # => ["#a"]
instance.instance_variable_get("#a") # => 123