Last active
March 16, 2019 01:35
-
-
Save sdball/5162135 to your computer and use it in GitHub Desktop.
Sometimes Ruby is Weird
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class NilWhatAreYouDoingStahp | |
attr_accessor :not_nil | |
def initialize | |
@not_nil = "I'm not nil! I'm a value!" | |
end | |
def wat | |
if not_nil.nil? | |
not_nil = "Ok, now I'm not nil." | |
end | |
not_nil | |
end | |
def omglol | |
not_nil | |
end | |
end | |
stahp = NilWhatAreYouDoingStahp.new | |
stahp.wat # => nil | |
stahp.omglol # => "I'm not nil! I'm a value!" |
Spot on! Another fun way to present this puzzle is to say that adding five characters makes the code work as expected. That's almost a giveaway though.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Although confusing at first this makes sense once you become familiar with the MRI internals (which is a bit of a sad requirement). This is because the Ruby parser pre scans scopes for the assignments of variables and processes them up to a certain extend. It doesn't assign any values yet though, instead it sets them to their default values (NilClass in this case).
In this particular bit of code Ruby sees that there's a possible local variable assignment in
Foo#wat
and as such pre-creates it. You can test this by addingp local_variables
between lines 8 and 9 and you'll see that it displays[:not_nil]
.Normally this wouldn't be an issue but since your local variable and the getter method are named the same way you get a conflict. In Ruby local variables have precedence over methods in the same scope. As a result this method will return the value of the local variable and not the getter.
To work around this issue one would have to use the following code:
An even better alternative would be to use local variables with a different name.