如果没有明确定义,变量“p”在ruby中从哪里得到它的值?

时间:2010-06-26 00:41:26

标签: ruby jruby irb

问题:p从哪里获取它的价值以及为什么会发生这种情况?

考虑这个irb会话:

me@somewhere:~$ irb
irb(main):001:0> a
NameError: undefined local variable or method `a' for main:Object
    from (irb):1
irb(main):002:0> foo
NameError: undefined local variable or method `foo' for main:Object
    from (irb):2
irb(main):003:0> p
=> nil
irb(main):004:0> p.class
=> NilClass
irb(main):005:0>

我从未定义p - 所以为什么它没有价值? afoo都未被识别,p有什么特别之处?我也没有找到Kernel#p

下列出的任何内容

上下文:我正在阅读所谓的"28 bytes of ruby joy",并假设p是一个变量,如:def p.method_missing *_ ...

(别担心:我不打算在nil上实际定义method_missing ...只研究一些ruby代码......)

3 个答案:

答案 0 :(得分:7)

p只是 Kernel 上的一种方法,它在其参数上调用inspect,生成这些对象的人类可读表示。如果你没有给它任何参数,它什么都不打印。但是,不管你传递了什么,它都会返回nil。请参阅 Kernel#p Object#inspect

电源提示:在Ruby 1.9中,如果您有方法并且不知道它来自何处,请使用method方法:

ruby-1.9.1-p378 > method(:p)
 => #<Method: Object(Kernel)#p>

一次一步,我们将其视为:

 p                            # We found a method called p.
 #p                           # It's an instance method.
 Object ... #p                # It's available on Object.
 Object(Kernel)#p             # It came from the Kernel module.

更新:OP提供了来自 this article 的一些背景信息,作者声称如果添加method_missing,您的生活会更轻松通过执行以下操作nil

def p.method_missing*_;p;end

这个有点混淆的代码应该被理解为:

  • 定义一个名为def的新方法(method_missing)。这会覆盖method_missing上的默认Object处理程序,当遇到它不理解的方法时,它只会引发NoMethodError
  • 此方法将使用名为p的内容。
  • 它接受任意数量的参数(*)并将它们存储在名为_的变量中。
  • 这些参数的结果称为p

第二个子弹在这里是棘手的部分。 def p.method_missing表示两种情况之一,具体取决于具体情况:

  • 以前定义的名为p的对象,在此范围内。
  • 一个名为p的方法,它在范围内,并且不传递任何参数。

对于def p.method_missing,我们的意思是,“这个方法是在对象上定义的,这是调用p而没有参数的结果”。在这种情况下,那是NilClass;如果您在没有参数的情况下致电p,则会获得nil。因此,这只是在NilClass上定义方法的一种简短的hacky方式。

注意:我绝对建议反对method_missing上定义nil。这是一个愚蠢而危险的策略,用于保存几行代码,因为它改变了nil的行为。不要这样做!

答案 1 :(得分:2)

p是一个方法,它打印其参数的inspect值并返回nil。没有争论,它根本就什么都不做。

它的文档在Kernel#p下,而不是Kernel::p(因为它是内核的实例方法)。

答案 2 :(得分:2)

pKernel模块的一种方法。这对调试很有用 - 它通过调用它上面的inspect打印出你给它的任何内部表示。如果你没有传递任何参数,它只会打印出nil

irb(main):001:0> p 11
11
=> 11
irb(main):002:0> Kernel::p [1,2] + [3,4]
[1, 2, 3, 4]
=> [1, 2, 3, 4]

结果在这里打印两次,因为它也会返回对象,然后irb也打印出来。