Kernel.pp вызывает NoMethodError в Ruby - PullRequest
2 голосов
/ 12 июня 2019

Я использую Ruby 2.6.3

Документы Ruby ri pp как:

выводит аргументы в красивой форме.

В любом случае, вфайл, когда я пишу и запускаю следующий код:

#!/usr/bin/ruby -w

Kernel.pp 'hi'
pp 'hi'

Я получаю NoMethodError.

Но как работает следующий код?

#!/usr/bin/ruby -w

pp 'hi'
Kernel.pp 'hi'

Вывод:

"hi"
"hi"

Вот скриншот

Ответы [ 2 ]

5 голосов
/ 12 июня 2019

Фактический метод pp реализован в модуле, поставляемом с Ruby, который также называется pp.В более старых Ruby, чтобы использовать метод, вы всегда должны были запускать

require 'pp'
pp "foo"

Более новые версии Ruby с удобным методом в Kernel#pp, для которого автоматически требуется модуль ppи запускает метод.После первого вызова этого метода (и, следовательно, с require модуля), прежний метод заменяется на фактически предназначенный метод pp.

Таким образом, если вы сначала запустите метод экземпляра pp (который доступен как частный метод для всех объектов в Ruby, которые включают в себя модуль Kernel, то есть для всех объектов), модуль pp загружается и становятся доступными другие методы (включая метод класса Kernel.pp).

4 голосов
/ 12 июня 2019

Это потому, что метод pp по умолчанию является закрытым методом модуля Kernel. Вот его источник :

def pp(*objs)
  require 'pp'
  pp(*objs)
end

Итак, как мы видим, он имеет побочный эффект загрузки pp файла. И, похоже, этот файл переопределяет метод pp, так как мы не получаем слишком большую ошибку стека из бесконечной рекурсии. Это действительно так. В pp файле источника у нас есть что-то вроде этого:

module Kernel
  # Returns a pretty printed object as a string.
  #
  # In order to use this method you must first require the PP module:
  #
  #   require 'pp'
  #
  # See the PP module for more information.
  def pretty_inspect
    PP.pp(self, ''.dup)
  end

  # prints arguments in pretty form.
  #
  # pp returns argument(s).
  def pp(*objs)
    objs.each {|obj|
      PP.pp(obj)
    }
    objs.size <= 1 ? objs.first : objs
  end
  module_function :pp
end

Итак, как мы видим, он переопределяет метод pp как открытый метод экземпляра ядра. Вот почему явный вызов pp до правильного вызова pp вызывает ошибку. И поэтому после правильного вызова pp ошибка исчезает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...