Ruby Koan: Constants become symbols
In the about_symbols.rb Ruby Koan (https://github.com/edgecase/ruby_koans), I have the following code:
RubyConstant = "What is the sound of one hand clapping?"
def test_constants_become_symbols
all_symbols = Symbol.all_symbols
assert_equal true, all_symbols.include?(:"nonexistent")
assert_equal true, all_symbols.include?(:"What is the sound of one hand clapping?")
assert_equal true, all_symbols.include?("What is the sound of one hand clapping?".to_sym)
end
As is, the 开发者_C百科test passes.
Three questions:
Why does the first assert pass?
:"nonexistent"
should not be included in all_symbols but it is included so I must be misunderstanding something.When I comment out the second assert, the test fails because
"What is the sound of one hand clapping?".to_sym
is not included in all_symbols whereas:"What is the sound of one hand clapping?"
is included. Since they are equivalent, why does the last assert fail? Also, why does it pass when the second assert is not commented out? (Why does the second assert have any effect on the third assert?)To my knowledge, the point of this Ruby Koan was to demonstrate that constants become symbols (at least, that's what I'm inferring from the method name). Since RubyConstant is a constant with the value
"What is the sound of one hand clapping?"
, why isn't"What is the sound of one hand clapping?".to_sym
included in the list of symbols? The only explanation that I can think of is that, contrary to the method name, constants do not in fact become symbols.
Thanks for your help!
hoha has it right but I'll try to expand and clarify a bit.
The interpreter will create the :nonexistent
symbol when it parses test_constants_become_symbols
. Then, when you run it, Symbol.all_symbols
is called to get a list of all known symbols and :nonexistent
is in the list. Also note that the double quotes on "nonexistent"
are a syntax issue rather than an internal representation issue so :nonexistent
and :"nonexistent"
are the same thing.
If you comment out this one:
assert_equal true, all_symbols.include?(:"What is the sound of one hand clapping?")
then the :"What is the sound of one hand clapping?"
symbol will not be seen by the parser and so it won't be in the all_symbols
array. The .to_sym
method call on the following line is executed when test_constants_become_symbols
is executed; so, the :"What is the sound of one hand clapping?"
symbol is created after you get your all_symbols
and this will fail:
assert_equal true, all_symbols.include?("What is the sound of one hand clapping?".to_sym)
If you execute test_constants_become_symbols
again in the same interpreter instance (with the second assert_equal
still commented out) then both uncommented assert_equal
calls will pass as the first run through test_constants_become_symbols
will create the :"What is the sound of one hand clapping?"
and the second Symbol.all_symbols
will include it in the returned array.
Running your code in irb
without wrapping it in a def
might help you see what's going on.
I'm not a Ruby guru but it looks like interpreter created this symbols during def
expression evaluation. That's why these symbols are already there when you call Symbol.all_symbols
. Third assert
fails with second one being commented out because "string".to_sym
creates symbol during methods execution i.e. after you got available symbols with all_symbols = Symbol.all_symbols
.
精彩评论