I've just discovered that return
s in following closure will return from function findPackage
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 =>
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)
}
logger.debug("Found package is {}", path)
path
}
Can I somehow do a local return please? Thank you.
Or you could get rid of your loop and replace it with what you're trying to do: "find"
def findPackage(name: String, suffix: Option[String] = None): Path = {
logger.debug("Looking for package {} with suffix {}", name, suffix)
def matching(path : Path) : Boolean = {
val matcher = packagePattern.matcher(path.getFileName.toString)
matcher.matches && matcher.group(1).equals(name) && (!suffix.isDefined || (matcher.group(2) != null && matcher.group(2).equals(suffix.get))
}
val path: Path = using(Files.newDirectoryStream(appDir)) {dirs =>
dirs find matching getOrElse {throw new PackageNotFoundException(this, name, suffix)}
}
logger.debug("Found package is {}", path)
path
}
I fully support James Iry'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 have added a try{}
block around the body of the anonymous function and then catch
expression at the end looking for scala.runtime.NonLocalReturnControl
exception, then I extract and pass on the return value.
Why it works?
Returning from a nested anonymous function raises scala.runtime.NonLocalReturnControl
exception which is caught by the host function or method.
Scala Language Spec, section 6.20 Return Expressions:
... Returning from a nested anonymous function is implemented by throwing and catching a scala.runtime.NonLocalReturnException. Any exception catches between the point of return and the enclosing methods might see the exception. A key comparison makes sure that these exceptions are only caught by the method instance which is terminated by the return.
If the return expression is itself part of an anonymous function, it is possible that the enclosing instance of f has already returned before the return expression is executed. In that case, the thrown scala.runtime.NonLocalReturnException will not be caught, and will propagate up the call stack.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With