Scala:模式匹配选项与案例 类 和代码块
Scala: pattern matching Option with case classes and code blocks
我开始学习很棒的 Scala 语言,我有一个关于 "deep" 模式匹配的问题
我有一个简单的 Request
class:
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")
}
}
看,我在 case
语句中使用 requestOrNone.get
来获取操作 Request
对象。它是类型安全的,因为 case
语句匹配吗?我觉得有点丑。这是从 Some
"unwrap" Request
对象但仍然能够匹配 Request
class 字段的方法吗?
如果我想在 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)
}
}
}
您可以如下重写模式(使用别名)。
case Some(req @ Request(_, _, _)) => new Response(405, "Method Not Allowed", req)
模式中不能使用代码块,只能使用守卫(if ...
)。
有像rich pattern matching这样的模式匹配编译器插件。
对于问题的第一部分,您可以将匹配的值命名为 @
:
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:模式绑定器):
A pattern binder x@p consists of a pattern variable x and a pattern p.
The type of the variable x is the static type T of the pattern p. This
pattern matches any value v matched by the pattern p, provided the
run-time type of v is also an instance of T , and it binds the
variable name to that value.
但是,在您的示例中,您 不需要 :因为您没有匹配 Request
的任何内容,而只是它的存在,您可以这样做:
case Some(req) => new Response(405, "Method Not Allowed", req)
对于第二部分,您可以嵌套 match
es。 Intellij 建议删除大括号的原因是它们是不必要的:关键字 case
足以知道前面的 case
已经完成。
至于这是否是一个好的做法,这显然取决于具体情况,但我可能会尝试将代码重构为更小的块。
我开始学习很棒的 Scala 语言,我有一个关于 "deep" 模式匹配的问题
我有一个简单的 Request
class:
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")
}
}
看,我在 case
语句中使用 requestOrNone.get
来获取操作 Request
对象。它是类型安全的,因为 case
语句匹配吗?我觉得有点丑。这是从 Some
"unwrap" Request
对象但仍然能够匹配 Request
class 字段的方法吗?
如果我想在 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)
}
}
}
您可以如下重写模式(使用别名)。
case Some(req @ Request(_, _, _)) => new Response(405, "Method Not Allowed", req)
模式中不能使用代码块,只能使用守卫(if ...
)。
有像rich pattern matching这样的模式匹配编译器插件。
对于问题的第一部分,您可以将匹配的值命名为 @
:
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:模式绑定器):
A pattern binder x@p consists of a pattern variable x and a pattern p. The type of the variable x is the static type T of the pattern p. This pattern matches any value v matched by the pattern p, provided the run-time type of v is also an instance of T , and it binds the variable name to that value.
但是,在您的示例中,您 不需要 :因为您没有匹配 Request
的任何内容,而只是它的存在,您可以这样做:
case Some(req) => new Response(405, "Method Not Allowed", req)
对于第二部分,您可以嵌套 match
es。 Intellij 建议删除大括号的原因是它们是不必要的:关键字 case
足以知道前面的 case
已经完成。
至于这是否是一个好的做法,这显然取决于具体情况,但我可能会尝试将代码重构为更小的块。