Scala:模式匹配选项包括案例类和代码块

时间:2015-05-13 07:06:43

标签: scala pattern-matching

我开始学习伟大的Scala语言ang有关于“深度”模式匹配的问题

我有一个简单的Request类:

case class Request(method: String, path: String, version: String) {}

一个函数,它尝试匹配request实例并构建相应的响应:

def guessResponse(requestOrNone: Option[Request]): Response = {
    requestOrNone match {
        case Some(Request("GET", path, _)) => Response.streamFromPath(path)
        case Some(Request(_, _, _)) => new Response(405, "Method Not Allowed", requestOrNone.get)
        case None => new Response(400, "Bad Request")
    }
}

请参阅我在requestOrNone.get语句中使用case来获取操作Request对象。是否类型安全,因为case语句匹配?我发现它有点难看。它是一种从Request“展开”Some对象的方式,但仍然可以匹配Request类字段吗?

如果我想在case内部使用局部变量等进行复杂计算,该怎么办...我可以在{}语句之后使用case块吗?我使用IntelliJ Idea与官方Scala插件,它突出显示我的括号,建议删除它们。

如果可以的话,将比赛括起来是不错的做法?

... match {
  case Some(Request("GET", path, _)) => {
      var stream = this.getStream(path)

      stream match {
        case Some(InputStream) => Response.stream(stream.get)
        case None => new Response(404, "Not Found)
      }
  }
}

2 个答案:

答案 0 :(得分:2)

对于问题的第一部分,您可以使用@为与之匹配的值命名:

scala> case class A(i: Int)
defined class A

scala> Option(A(1)) match {
     |   case None => A(0)
     |   case Some(a @ A(_)) => a
     | }
res0: A = A(1)

来自Scala Specifications 8.1.3:模式文件夹):

  

图案装订器x @ p由图案变量x和图案p组成。   变量x的类型是模式p的静态类型T.这个   模式匹配模式p匹配的任何值v,条件是   运行时类型v也是T的一个实例,它绑定了   变量名到该值。

但是,在您的示例中,您不需要 :因为您不能与Request的任何内容进行匹配,而只是匹配它的存在,您可以这样做:

case Some(req) => new Response(405, "Method Not Allowed", req)

对于第二部分,您可以嵌套match es。 Intellij建议删除大括号的原因是它们是不必要的:关键字case足以知道之前的case已完成。

至于它是否是一个好的做法,显然取决于具体情况,但我可能会尝试将代码重构为更小的块。

答案 1 :(得分:0)

您可以按以下方式重写模式(使用别名)。

case Some(req @ Request(_, _, _)) => new Response(405, "Method Not Allowed", req)

您不能在模式中使用代码块,只能使用保护(if ...)。

有模式匹配编译器插件,如rich pattern matching