Руби Коан: Константы становятся символами - PullRequest
11 голосов
/ 19 марта 2011

В about_symbols.rb Руби Коан (https://github.com/edgecase/ruby_koans), У меня есть следующий код:

    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

Как есть, тест проходит.

Три вопроса:

  1. Почему первый утверждение проходит? :"nonexistent" не следует включать в all_symbols, но он включен, поэтому я должен что-то неправильно понять.

  2. Когда я закомментирую второе утверждение, тест не пройден, потому что "What is the sound of one hand clapping?".to_sym не включен в all_symbols, тогда как :"What is the sound of one hand clapping?" включен. Поскольку они эквивалентны, почему последнее утверждение терпит неудачу? Кроме того, почему это проходит, когда второе утверждение не закомментировано? (Почему второе утверждение влияет на третье утверждение?)

  3. Насколько мне известно, цель этого Руби Коана состояла в том, чтобы продемонстрировать, что константы становятся символами (по крайней мере, это то, что я понимаю из названия метода). Поскольку RubyConstant является константой со значением "What is the sound of one hand clapping?", почему "What is the sound of one hand clapping?".to_sym не включен в список символов? Единственное объяснение, которое я могу придумать, состоит в том, что, вопреки названию метода, константы фактически не становятся символами.

Спасибо за вашу помощь!

Ответы [ 2 ]

7 голосов
/ 19 марта 2011

хоха все правильно, но я попытаюсь немного расширить и уточнить.

Интерпретатор создаст символ :nonexistent при разборе test_constants_become_symbols.Затем, когда вы запускаете его, вызывается Symbol.all_symbols, чтобы получить список всех известных символов, а :nonexistent находится в списке.Также обратите внимание, что двойные кавычки в "nonexistent" являются проблемой синтаксиса, а не внутренней проблемой представления, поэтому :nonexistent и :"nonexistent" - это одно и то же.

Если вы закомментируете это:

  assert_equal true, all_symbols.include?(:"What is the sound of one hand clapping?")

, тогда символ :"What is the sound of one hand clapping?" не будет виден синтаксическим анализатором и не будет в массиве all_symbols.Вызов метода .to_sym в следующей строке выполняется при выполнении test_constants_become_symbols;Итак, символ :"What is the sound of one hand clapping?" создается после того, как вы получите all_symbols, и это не удастся:

  assert_equal true, all_symbols.include?("What is the sound of one hand clapping?".to_sym)

Если вы снова выполните test_constants_become_symbols в том же экземпляре интерпретатора (со вторым assert_equal все ещезакомментировано), тогда оба незакомментированных assert_equal вызова пройдут, так как первый прогон через test_constants_become_symbols создаст :"What is the sound of one hand clapping?", а второй Symbol.all_symbols включит его в возвращенный массив.

Запуск вашего кода вirb без включения в def может помочь вам увидеть, что происходит.

3 голосов
/ 19 марта 2011

Я не гуру по Ruby, но похоже, что интерпретатор создал эти символы во время def вычисления выражения. Вот почему эти символы уже есть, когда вы звоните Symbol.all_symbols. Третий assert завершается неудачно, второй комментируется, потому что "string".to_sym создает символ во время выполнения методов, т.е. после того, как вы получили доступные символы с all_symbols = Symbol.all_symbols.

...