Откуда переменная "p" получает свое значение в ruby, если она не определена явно? - PullRequest
4 голосов
/ 26 июня 2010

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

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

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

Ответы [ 3 ]

7 голосов
/ 26 июня 2010

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.

Обновление: ОП предоставил некоторый контекст из этой статьи , где автор утверждает, что ваша жизнь станет проще, если вы добавите 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.Не делай этого!

2 голосов
/ 26 июня 2010

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.

2 голосов
/ 26 июня 2010

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

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

...