I fully support James Irie's suggestion, but for the sake of demonstration:
def findPackage(name: String, suffix: Option[String] = None): Path = { logger.debug("Looking for package {} with suffix {}", name, suffix) val path: Path = using(Files.newDirectoryStream(appDir)) {dirs => try { for (val path <- dirs) { val matcher = packagePattern.matcher(path.getFileName.toString) if (matcher.matches() && matcher.group(1).equals(name)) if (suffix.isDefined) { if (matcher.group(2) != null && matcher.group(2).equals(suffix.get)) return path } else return path } throw new PackageNotFoundException(this, name, suffix) } catch { case e:scala.runtime.NonLocalReturnControl[Path] => e.value} } logger.debug("Found package is {}", path) path }
What changed?
I added a try{} block around the body of the anonymous function, and then the catch expression at the end looks for scala.runtime.NonLocalReturnControl exception, then I extract and pass the return value.
Why does it work?
Returning from a nested anonymous function throws a scala.runtime.NonLocalReturnControl exception, which is caught by the host function or method.
Scala Language Specification , Section 6.20. Return Expressions:
... The return from the nested anonymous function is thrown and caught by scala.runtime.NonLocalReturnException. Any exception delayed between the return point and the enclosing methods may see the exception. A key comparison ensures that these exceptions are caught only by the method instance, which is completed by the return.
If the return statement itself is part of an anonymous function, it is possible that the environment instance f has already returned before executing the return statement. In this case, the thrown scala.runtime.NonLocalReturnException will not be caught and will distribute the call stack.
source share