Ruby Koan: Constants become symbols

感情迁移 提交于 2019-12-29 04:48:20

问题


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 test passes.

Three questions:

  1. Why does the first assert pass? :"nonexistent" should not be included in all_symbols but it is included so I must be misunderstanding something.

  2. 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?)

  3. 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!


回答1:


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.




回答2:


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.



来源:https://stackoverflow.com/questions/5358727/ruby-koan-constants-become-symbols

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!