Поскольку вы попросили интуицию, чтобы решить эту проблему в общем.Позвольте мне начать с основы.
Scala - это (между прочим) функциональный язык программирования, поэтому для нас существует очень важная концепция.И дело в том, что мы пишем программы, составляя expressions
, а не statements
.
Таким образом, концепция возвращаемого значения для нас означает оценку expression
.
(Примечание.это связано с понятием ссылочная прозрачность ) .
val a = expr // a is bounded to the evaluation of expr,
val b = (a, a) // and they are interchangeable, thus b === (expr, expr)
Как это относится к вашему вопросу.В том смысле, что у нас действительно нет структур управления, но есть сложные выражения.Например, if
val a = if (expr) exprA else exprB // if itself is an expression, that returns other expressions.
Таким образом, вместо того, чтобы делать что-то вроде этого:
def foo(a: Int): Int =
if (a != 0) {
val b = a * a
return b
}
return -1
Мы бы сделали что-то вроде:
def foo(a: Int): Int =
if (a != 0)
a * a
else
-1
Потому что мы можемсвязать все выражение if
как тело foo.
Теперь вернемся к вашему конкретному вопросу.Как мы можем досрочно вернуть cycle
?
Ответ: вы не можете, по крайней мере, не без мутаций.Но вы можете использовать более высокую концепцию, вместо итерации , вы можете пройти что-то.И вы можете сделать это, используя recursion
.
Таким образом, давайте реализуем find
, предложенный @Thilo, как tail-recursive
функцию.
(Очень важно, чтобыфункция является рекурсивной по хвосту, поэтому компилятор оптимизирует ее как нечто эквивалентное циклу while, чтобы мы не взорвали стек) .
def find(start: Int, end: Int, step: Int = 1)(predicate: Int => Boolean): Option[Int] = {
@annotation.tailrec
def loop(current: Int): Option[Int] =
if (current == end)
None // Base case.
else if (predicate(current))
Some(current) // Early return.
else
loop(current + step) // Recursive step.
loop(current = start)
}
find(0, 10000)(_ == 10)
// res: Option[Int] = Some(10)
Или мы можем немного обобщить этоподробнее, давайте реализуем поиск для списков любых типов элементов.
def find[T](list: List[T])(predicate: T => Boolean): Option[T] = {
@annotation.tailrec
def loop(remaining: List[T]): Option[T] =
remaining match {
case Nil => None
case t :: _ if (predicate(t)) => Some(t)
case _ :: tail => loop(remaining = tail)
}
loop(remaining = list)
}