Как объясняется в другом ответе, использование return
в scala - плохая идея и анти-паттерн. Но что еще хуже использует return
внутри лямбда-функции (как ваш закомментированный код внутри foreach
): это на самом деле выдает исключение, которое затем перехватывается снаружи для выхода из основной функции ,
В результате тело вашей функции скомпилировано во что-то вроде:
def foo(nodes: List[Node]) = {
val handle = new AnyRef
try {
nodes.foreach { n =>
if(n.id == "foo") throw new NonLocalReturnControl(handle, currentLevel)
...
foo(nextNodes)
} catch {
case nlrc: NonLocalReturnControl[Int] if nlrc.key == handle => nlrc.value
}
}
Как вы можете видеть, ваш рекурсивный вызов здесь не в хвостовой позиции, поэтому ошибка компилятора ле git.
Еще одним идиоматическим c способом написать то, что вы хотите, будет деконструкция списка и использование самой рекурсии в качестве «движка» для l oop:
def searchNodes(nodes: List[Node], end: String) = {
@tailrec def doSearch(
nodes: List[(Node, Int)],
visited: List[Node],
end: String
) : Int = nodes match {
case Nil => -1
case (node, level) :: tail if node.id == end => level
case (node, level) :: tail =>
doSearch(
tail ::: node.addAdjacentNodes(visited).map(_ -> level+1),
node :: visited,
end
)
}
doSearch(nodes.map(_ -> 0), Nil, end)
}