2012-03-14 54 views
4

我刚刚发现return S IN关闭后会从功能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 
} 

回报会我不知做了本地回报吗?谢谢。

回答

4

是的,你可以通过定义一个本地方法:

def findPackage(name: String, suffix: Option[String] = None): Path = { 
    logger.debug("Looking for package {} with suffix {}", name, suffix) 

    def search(dirs: List[File]) = { // not sure what the type of dirs actually is 
     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) 
    } 

    val path: Path = using(Files.newDirectoryStream(appDir))(search _) 
    logger.debug("Found package is {}", path) 
    path 
} 

或通过抛出一些异常,并捕获它:

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)) 
          throw new ReturnException(path) 
        } else 
         throw new ReturnException(path) 
      } 
      throw new PackageNotFoundException(this, name, suffix) 
     } 
     catch { case ReturnException(path) => path } 
    } 
    logger.debug("Found package is {}", path) 
    path 
} 
8

我完全支持詹姆斯IRY的建议,但为求示范:

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 
} 

什么改变?

我添加了一个try{}块周围的匿名函数的体上,然后在端部catch表达寻找scala.runtime.NonLocalReturnControl异常,那么我提取并传递返回值。

为什么它有效?

从嵌套匿名函数返回引发scala.runtime.NonLocalReturnControl异常,它被主机函数或方法捕获。

Scala Language Spec,第6.20节返回表达式:

...从嵌套的匿名函数返回由 投掷实现,受凉scala.runtime.NonLocalReturnException。返回点与封闭方法之间的任何 异常捕获可能会看到异常。一个关键的比较可以确保 这些异常仅被返回终止的 方法实例捕获。

如果返回表达式本身是匿名函数的一部分,则在执行返回表达式之前,其封闭实例f已经返回 ,因此它可能是 。在这种情况下,抛出的 scala.runtime.NonLocalReturnException将不会被捕获,并且 会向上传播调用堆栈。

10

或者你可以摆脱你的循环,并与你想要做什么替代它:“查找”

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 
} 
0

我也有类似的麻烦,我通过传播任何ControlThrowable解决它我可能会发现,像它说here

def asJson: JsValue = { 
    val key = "classification.ws.endpoint" 

    configuration.getString(key).map{ url => 
    try { 
     return WS.url(url).get().await.get.json 
    } catch { 
     case ce : scala.util.control.ControlThrowable => throw ce 
     case e => throw InvalidWebServiceResponseException("Error accessing '%s'".format(url), e) 
    } 
    }.getOrElse { 
    throw new MissingConfigurationException("No value found for '%s' configuration".format(key)) 
    } 

} 

注意,在这种情况下,仅仅取消“返回”语句解决了这个问题...