2012-03-14 51 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)) 
    } 

} 

注意,在這種情況下,僅僅取消「返回」語句解決了這個問題...