2016-02-12 2 views
0

Я надеюсь, вы, ребята, поможете мне решить, какое поведение будет более «стандартным» или «ожидаемым».Значение аргумента аргумента метода Ruby, неявное vs literal nil, ответственность библиотеки или вызывающие?

фона:

В Ruby вы можете предоставить аргументы по умолчанию для метода, например.

def tester(input={}) 
    input 
end 

Если вы звоните tester вы получаете {}. Однако если вы звоните tester(nil), вы получаете nil.

Честно говоря, что меня удивило, я полагал, что вы получите {}, если вы прошли nil методу, потому что я всегда представлял заявление input={} в определении метода быть сродни input ||= {}, но очевидно, что это больше похоже defined?(input) ? input : {}.

Вопрос:

В библиотеке я утверждаю, у меня есть класс, который принимает необязательный хэш инициализации. Инициализатором выглядит точно так же, как тестер выше:

def initialize(input={}) 

Таким образом, вы можете позвонить MyClass.new или MyClass.new foo:1, но вы не можете назвать MyClass.new nil

Это кажется очевидным, за исключением случаев использования переменных инициализации, например. MyClass.new(opts), где opts может быть хэш или ноль.

Я мог бы изменить способ это работает, изменяя реализацию, как так:

def initialize(input=nil) 
    input ||= {} 
    ... 
end 

Но я оставил интересно, это правильный дизайн для интерфейса Ruby?

Должен ли я ожидать, что вызывающий абонент будет использовать MyClass.new(opts || {})?

Если вы используете библиотеку, и есть класс в этой библиотеке, который принимает необязательный хеш, вы ожидаете, что будет безопасно передать nil инициализатору и для этого следует рассматривать как эквивалент пропуска без аргумента ? Или вы ожидаете, что это сломается, потому что в Ruby, проходящий буквальный ноль, это не то же самое, что передать аргумент?

Какой дизайн выглядит более «правильным» для вас?

+0

Либо. Это зависит от ожидаемых шаблонов использования. – jrochkind

ответ

2

По умолчанию применяются только к неуказанные аргументы, а не те, которые поставляются, но nil. В Ruby это значение, объект даже, он не похож на другие языки с «неопределенным» или «нулевым».

Ваше наблюдение за использованием ||= { } - это то, как много библиотек обрабатывают подобные вещи. Я обычно разрабатываю код, чтобы быть устойчивым перед лицом прохождения nil случайно, поскольку это может произойти по ошибке и кажется разумной интерпретацией того, как делать то, что я имею в виду, не будучи чрезмерно параноидальным и защитным.

Обычно это только проблема с ситуациями = { } или = [ ]. В некотором смысле это принцип Руби, передающий нечто, что достаточно близко для работы или, по крайней мере, неверно. Подумайте о том, как этот метод можно использовать и учитывать все разумные ситуации.

Так подписи вы склонны видеть выглядеть следующим образом:

def with_options(args = nil) 
    # Default arguments to an empty Hash 
    args ||= { } 

    # ... 
end 

def trim(string, length = 1) 
    string = string.to_s # Coerce to string 
    length = length.to_i # Coerce to integer 

    # ... 
end 

Для кода, который используется внутри это вообще лучше, чтобы быть более строгими и ошибки бросить, если методы используются неправильно, то есть менее оборонительный, но для методов, которые должны использоваться различными партиями, которые могут не получить абсолютно все, правильнее оценить степень широты в том, что входит в нее, всегда оценивается.

Передача в "1" вместо 1 для численного аргумента слишком проста в среде, такой как Rails, и наказание за то, что кто-то не правильно произносит, возможно, слишком жесток. По крайней мере, попробуйте конвертировать и обработать результат.

+1

Да, я думаю, вы проиллюстрируете мое quandry: технически передача «nil» является ошибкой вызывающих », но это« неумолимая »позиция в необязательном аргументе для класса библиотеки. Это полезная обратная связь, спасибо! – Andrew

Смежные вопросы