我正在使用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
答案 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
之后,错误消失了的原因。