2013-11-17 3 views
1

Я Я новичок в Ruby, и пытается понять, почему это работает (это, кажется, по крайней мере, по "the Master"):неявной значение, если /, если заявление в рубине

def array_of_fixnums?(array) 
    true unless array.find { |item| item.class != Fixnum } 
end 

Меня беспокоит то, где «ложность» возникает, когда массив содержит нефиксированные значения. Правильно ли я предполагаю, что в заявлении unless нет неявного «else false»? В этом случае я предполагаю, что он должен поступать из значения nil, возвращаемого Enumerable#find. Это верно?

Если да, это кажется немного шатким. Может быть, лучше вернуть false явно, вот так?

array.find { |item| item.class != Fixnum } ? false : true 

Есть ли другой, лучший способ полностью? Спасибо, что помогли мне обернуть мою голову вокруг этого и для любых предложений «лучшей практики».

+0

Почему вы считаете «ноль» ложным шатком? – steenslag

+0

Ноль не возвращается из array.find(), но из-за того, что ваш метод не имеет возвращаемого значения (следовательно, nil) в случае, когда массив содержит значение, отличное от Fixnum. Решение array.all() ниже, потому что оно более явное. – AndyV

ответ

3

Ваш метод возвращает nil не потому, что find возвращается nil, а потому, что если ваш встроенный условный не проходит, то метод не имеет явного возвращаемого значения. Это было бы более понятно, если бы не встраивать, считают:

def array_of_fixnums?(array) 
    unless array.find { |item| item.class != Fixnum } 
    return true 
    end 
    # otherwise don't explicitly return (implicit nil) 
end 

Опираясь на falsiness из nil будет часто работа, это проблематично в том, что она не следовать принципу наименьшего удивления. A ? метод должен вернуть true или false.

Но ваш метод имеет более серьезные проблемы. Он использует путаную логику (двойной отрицательный), а сам полагается на фальшивость nil и правду неnil, чтобы функционировать. Подумайте, что произойдет, если ваш метод прошел [false]. К сожалению.

Лучше всего было бы что-то вроде:

array.all? {|n| n.is_a? Fixnum } 

Полагают, что этот метод делает именно то, что он говорит, ясно.

Возвращение булева явно, хотя и не обязательно неправильное, является излишним и часто считается плохой практикой. Скорее рассмотрим пример, который говорит, в ruby ​​говорят, - это одно из значений в этом массиве Fixnum?.Результат заключается в том, что выражение - это метод, нет причин для его оценки, а затем вернуть true|false.

+0

А, это имеет смысл! Я знаю, что методы ruby ​​вернут любую последнюю выполненную команду; Наверное, я никогда не думал о том, что произойдет, если бы это было условно. Приветствия за помощь - метод 'array # all' намного приятнее. – ebarrere

1

От метода находки документа:

Passes each entry in enum to block. Returns the first for which block is not false. If no object matches, calls ifnone and returns its result when it is specified, or returns nil otherwise. 

Таким образом, все, что вам нужно:

def array_of_fixnums?(array) 
    array.find { |item| item.class != Fixnum } 
end 

Если что-нибудь будет найдено, который будет возвращена, в противном случае ноль будет возвращен, и метод будет оценивать значение false.

Однако, как возвращение пункта может быть false или nil (если какой-либо элемент в списке является ложным или нет), я бы рекомендовал использовать метод .any? вместо этого.

def array_of_fixnums?(array) 
    array.any? { |item| item.class != Fixnum } 
end 
0

Давайте посмотрим, почему true unless condition работает так же, как он.

Я считаю, что x unless condition был представлен как эстетическое улучшение до x if !condition, но эти два эквивалента (и, на мой взгляд, это улучшение). Чтобы избавиться от двойных негативов, я просто рассмотрю x if condition.

Один из основных принципов Ruby заключается в том, что каждый оператор должен возвращать значение (а именно, последнее оцениваемое выражение). Поэтому x if condition должен оцениваться как if condition then x else y end. Но что такое y? Если y оценивается как true или false, x if condition будет бессмысленным, если x является булевым выражением. Чтобы понять, почему, считают:

w = (x == 5 if z == 6) 

Если w были верны, мы можем заключить, что x = 5 и z = 6, но если w были ложными, мы не знаем, является ли z = 6 и x != 5 или z != 6 и x = 5 или x != 5. Учитывая, что любое значение y, отличное от nil, оценивается как true или false, единственным разумным значением для y является nil. Таким образом, будет доступно if w == nil. Конечно, это все еще проблема (в других ситуациях), когда x может быть nil.

Я хотел бы получить разъяснения и уточнения. Возможно, есть еще менее запутанный способ сделать этот аргумент.

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