2010-06-26 4 views
4

Вопрос: Где p получить значение снизу и почему это происходит?Где переменная «p» получает ее значение из ruby, если она не определена явно?

Рассмотрим IRB сессию:

[email protected]:~$ 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 - так почему это ноль котируется? Ни a, ни foo не были признаны, так что особенного о p? Я также не нашел ничего в списке под Kernel#p

Контекст: Я читаю так называемый "28 bytes of ruby joy" и предположил p была переменная, как: def p.method_missing *_ ...

(Не волнуйтесь, : Я не собираюсь на самом деле определять method_missing на ноль везде ... просто изучая некоторый код ruby ​​...)

ответ

7

p просто метод на Kernel который называет inspect по своим аргументам, производя удобочитаемых представления этих объектов. Если вы не дадите ему никаких аргументов, он ничего не печатает. Несмотря на то, что вы его передаете, он возвращает nil. См. Kernel#p и Object#inspect.

Контроллер питания: В рубине 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. 

Update: ОП при условии, некоторый контекст из 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.

Примечание: Я определенно рекомендую против определения method_missing на nil. Это глупая и опасная тактика, используемая для сохранения нескольких строк кода, поскольку она изменяет поведение nil. Не делай этого!

+0

Я согласен: я думаю, что 28-байтовый подход интересен с точки зрения дизайна, но опасно изменить такое глобальное предположение, учитывая __другие люди могут полагаться на исключения, вызванные обменом сообщениями nil__. (Это от «о нет!», Они обнаружили метапрограмму «школы проблем обслуживания ...») – daf

2

p - метод, который печатает значение своих аргументов и возвращает нуль. Без аргументов он просто ничего не делает.

Его документация находится под Kernel#p, а не Kernel::p (потому что это метод экземпляра ядра).

2

p - это метод модуля Kernel. Это хорошо для отладки - он печатает внутреннее представление того, что вы ему даете, называя 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.

+3

На самом деле он ничего не выводит, если не задано никаких аргументов. 'nil' - это возвращаемое значение. http://www.ruby-doc.org/core/classes/Kernel.html#M005961 –