是否可以从功能体中取消当前的部分功能?

时间:2014-07-08 13:23:11

标签: scala pattern-matching partialfunction

我需要定义一些部分函数来处理具有不同模式的不同url(使用unfinagled):

def indexRoute:PartialFunction[Request, Response] = { 
   case Path("index") => Ok ~> ResponseString("hello")
}

def notFound:PartialFunction[Request, Response] = { 
    case Path(_) => NotFound
}

def assetsRoutes:PartialFunction[Request, Response] = { 
    case Path("assets" :: tail) =>
      loadResourceContent(tail) match {
          case Some(content) => Ok ~> ResponseString(content)
          case _ => NotFound // !!! I don't want to handle it here
      }
}

val allRoutes = indexRoute orElse assetsRoutes orElse notFound

你可以看到我最终将一些部分功能组合成一个完整的路线。最后一个是NotFound处理不匹配的网址,所以我不想关心早期路线中的不匹配情况(例如assertRoutes)。

但在assetsRoutes方法中,我无法轻易检查case部分中是否存在资产,因为我只想触摸一次资产的文件系统。所以我不想写:

def assetsRoutes:PartialFunction[Request, Response] = { 
    case Path("assets" :: tail) if resoueceExist(tail)=>
      val content = loadResourceContent(tail).get 
      Ok ~> ResponseString(content)
}

虽然我可以写一个自定义unapply,如:

object AssetExistWithContent {

  def unapply(req:Request): Option[String] =  {
    req match {
      case Path("assets" :: tail) => loadResourceContent(tail)
      case _ => None
    }
  }
}

def assetsRoutes:PartialFunction[Request, Response] = { 
    case AssetExistWithContent(content) => Ok ~> ResponseString(content)
}

但我认为在匹配网址或请求时看到case AssetExistWithContent(content)部分并不清楚。

所以我想知道是否有可能取消功能体中的当前部分功能?所以我可以写:

def assetsRoutes:PartialFunction[Request, Response] = { 
    case Path("assets" :: tail) =>
      loadResourceContent(tail) match {
          case Some(content) => Ok ~> ResponseString(content)
          case _ => cancelThisPartialFunction // !!!
      }
}

我不需要关心何时使用此方法(NotFound或其他内容),只需告诉来电者我无法处理,请尝试下一个。

1 个答案:

答案 0 :(得分:3)

如您所述,无法取消PartialFunction。但是,您可以定义一个更简单的提取器:

object LoadableContent {
  def unapply(req: List[String]): Option[String] = loadResourceContent(req)
}

并使用它:

def assetsRoutes: PartialFunction[Request, Response] = { 
    case Path("assets" :: LoadableContent(content)) =>
      Ok ~> ResponseString(content)
}