Неявная область возвращаемого значения в Ruby
Я использую самоопределение include?
метод для изучения разницы между явным и неявным возвратом. Я это понимаю #each
возвращает коллекцию итеративно, поэтому я считаю, что мне нужно поместить мои истинные / ложные неявные возвращения в правильное место, но когда я это делаю, я возвращаю коллекцию, и я не уверен, что нужно изменить.
def self.include?(array, search_item)
array.each do |elem|
if elem == search_item
true
end
end
end
Ниже приведены тесты, которые я проверяю, но я не понимаю, как правильно сопоставить результаты. Почему они не совпадают или как я должен понимать сферу неявного возврата?
result = MethodReturns.include?(numbers_array, 4)
expect(result).to eq(true)
result = MethodReturns.include?(numbers_array, 7)
expect(result).to eq(false)
3 ответа
Вы хотите изменить на:
def self.include?(array, search_item)
array.each do |elem|
if elem == search_item
return true
end
end
return false
end
Причина этого заключается в том, что последний оператор в методе является возвращаемым значением. В вашем случае вы никогда не вернете false, если нет совпадений. Обязательно добавьте return
когда вы хотите разорвать и немедленно прекратить выполнение остальных методов.
Выполненный оператор LAST предоставляет возвращаемое значение. Последним, что происходит в цикле each(), всегда будет конец цикла (если только вы не выйдете из цикла каким-либо образом, например, return, break):
def do_stuff()
[1, 2, 3]. each do |num|
true if num == num
end
end
p do_stuff
--output:--
[1, 2, 3]
Таким образом, ваше истинное значение отбрасывается, и затем итерация с each() продолжается до тех пор, пока не завершится цикл each(), и, как вы знаете, когда завершится цикл each(), он возвращает левую часть.
Вот пример метода, который неявно возвращает true:
def do_stuff()
[1, 2, 3]. each do |num|
#blah
end
true
end
Метод each() по-прежнему возвращает массив, но метод each() не является оператором LAST, который выполняется в методе do_stuff().
В вашем примере вы можете сделать это:
def do_stuff(target)
found = false
[1, 2, 3]. each do |num|
found = true if num == target
end
found
end
p do_stuff(2)
--output:--
true
Однако это решение тратит впустую ресурсы, потому что метод each() продолжает итерацию по массиву после того, как найдено совпадение. Например, если в вашем массиве было 1 миллион элементов, и было найдено совпадение с индексом 0 в массиве, метод each() без необходимости продолжал бы итерацию по оставшимся 999 999 элементам. С другой стороны, явный возврат при обнаружении совпадения завершит цикл.
Явно писать никогда не ошибочно return val
, По мере того, как вы становитесь более опытным, вы можете отбросить часть возврата - КОГДА ПОДХОДИТ - чтобы показать мир, в котором вы знаете рубин... однако время от времени опуская return
все равно сбьет тебя с толку.
Если вы используете явный return
внутри вашего each
block - достижение этого кода приведет к немедленному возвращению значения (остановка итерации). Это из-за нелокальной возможности возврата блоков:
Блоки Ruby поддерживают non-local-return, что означает, что возврат из блока ведет себя идентично возврату из исходного контекста блока.
Так что ваш код должен работать правильно, если вы просто используете явный return
:
def self.include?(array, search_item)
array.each do |elem|
if elem == search_item
return true
end
end
end