Передача знака nil в качестве аргумента

Все значения для b ниже позволяют мне вызывать метод с синтаксисом *args.

def some_method(a)
   puts a
end

b = 1
some_method(*b) # => 1

b = false
some_method(*b) # => false

b = "whatever"
some_method(*b) # => "whatever"

С nil я ожидал получить nil, а не ошибку аргумента:

b = nil
some_method(*b) # => ArgumentError: wrong number of arguments (0 for 1)

Что здесь происходит?


person Automatico    schedule 01.06.2014    source источник
comment
Интересно, что это нарушает ссылочную прозрачность, попробуйте сделать b = *nil; method(b), и он отлично работает.   -  person Mike H-R    schedule 02.06.2014
comment
На менее связанной с этим ноте я бы нервничал, вызывая метод method. он творит жуткие вещи с моим pry (начинает печатать :inspect). Я предполагаю, что вы не будете делать это нормально, но я подумал, что это интересно, поэтому я подумал, что упомяну об этом, мне было бы интересно, если бы кто-нибудь мог сказать мне, что является причиной этого.   -  person Mike H-R    schedule 02.06.2014
comment
Ну, я не думаю, что я действительно могу это сделать. Дело в том, что я занимаюсь некоторым метапрограммированием, в котором проходящий материал может быть любым значением, включая nil, но, возможно, и массивом. Так что мне нужно, чтобы это было method(*b). И да, метод имени для метода не годится. Был просто примером здесь.   -  person Automatico    schedule 02.06.2014
comment
Я подозреваю, что у него может быть что-то, что nil не является подходящим объектом или что-то в этом роде. Но неплохо бы знать.   -  person Automatico    schedule 02.06.2014
comment
Я согласен, что было бы неплохо знать, поэтому я хочу следить за вопросом (и почему я проголосовал за вас), но вы можете устранить эту проблему в этом случае, добавив дополнительную строку, говорящую b= *b, так как это принудит nil в [], и массивы останутся прежними.   -  person Mike H-R    schedule 02.06.2014
comment
Ах, как и b= *b; some_method(*b)? Это может сработать.   -  person Automatico    schedule 02.06.2014
comment
Да, я не собираюсь публиковать это как ответ, поскольку он не отвечает на вопрос (о том, какая темная магия заразила nil рубина), но это, по крайней мере, решение. :)   -  person Mike H-R    schedule 02.06.2014
comment
Я думаю, что b = [] if b == nil на самом деле было бы понятнее и лучше, но да. Что происходит с нулем?   -  person Automatico    schedule 02.06.2014
comment
@MikeH-R: уже есть Object#method поэтому вызов собственного метода method не сработает.   -  person mu is too short    schedule 02.06.2014
comment
@muistooshort Я сделал эту ошибку в своем первоначальном вопросе, если вы проверите историю.   -  person Automatico    schedule 02.06.2014
comment
@muistooshort согласился. Я просто не понимаю, что именно он делает под капотом. Я ожидаю, что он переопределит метод по умолчанию тем, который мы определили. Чего я не понимаю, так это того, что в моем pry он начинает печатать :inspect каждый раз, когда печатается строка.   -  person Mike H-R    schedule 02.06.2014


Ответы (1)


Оператор splat * сначала применяет to_a к объекту, если он не является массивом и на нем определен to_a. Для чисел, ложных классов и строк to_a не определено, и они остаются самими собой. Для nilclass определяется to_a и возвращает пустой массив. Когда они разделены, цифры, ложный класс и строки остаются самими собой, но пустой массив становится отсутствием чего-либо. Также см. ответ на этот вопрос.

person sawa    schedule 02.06.2014
comment
Благодарю за разъяснение. Приятно знать правильное название. Нашел несколько документов на ruby-doc.org. - person Automatico; 02.06.2014