Kernel.pp在Ruby中引发NoMethodError

时间:2019-06-12 07:59:51

标签: ruby

我正在使用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"

这里是screenshot

2 个答案:

答案 0 :(得分:5)

实际的pp方法是在Ruby随附的模块中实现的,该模块也称为pp。对于较旧的红宝石,要使用该方法,必须始终运行

require 'pp'
pp "foo"

新红宝石在Kernel#pp中附带了一种便捷方法,该方法自动需要pp模块并运行该方法。首次调用此方法(并因此使用模块的require)之后,将前一个方法替换为实际使用的pp方法。

因此,如果您首先运行实例方法pp(可在Ruby中所有包含Kernel模块的对象上作为私有方法使用,即所有对象),则{{1 }}模块已加载,其他方法(包括pp类方法)变为可用。

答案 1 :(得分:4)

这是因为pp方法默认为Kernel模块的私有方法。这是它的source

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

因此,如我们所见,它具有加载pp文件的副作用。似乎此文件重新定义了pp方法,因为我们不会从无限递归中得到堆栈太深的错误。确实是这样。在pp file source中,我们有类似以下内容:

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之后,错误消失了的原因。