[英]Scala: pattern matching Option with case classes and code blocks
我開始學習出色的Scala語言,並且對“深度”模式匹配有疑問
我有一個簡單的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")
}
}
看,我在case
語句中使用requestOrNone.get
來獲取操作Request
對象。 由於case
語句匹配,類型安全嗎? 我覺得有點難看。 是否可以從Some
“解包” Request
對象,但仍然能夠匹配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)
}
}
}
對於問題的第一部分,可以使用@
命名匹配的值:
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規范 ( 8.1.3:模式綁定器 ):
模式綁定器x @ p由模式變量x和模式p組成。 變量x的類型是模式p的靜態類型T。 如果v的運行時類型也是T的實例,則此模式匹配與模式p匹配的任何值v,並且它將變量名綁定到該值。
但是,您無需在示例中進行操作:由於您沒有與Request
任何內容匹配,而只是與Request
,因此您可以:
case Some(req) => new Response(405, "Method Not Allowed", req)
對於第二部分,您可以嵌套match
es。 Intellij建議刪除括號的原因是它們是不必要的:關鍵字case
足以知道前面的case
已完成。
至於是否是一個好習慣,這顯然取決於情況,但是我可能會嘗試將代碼重構為較小的塊。
您可以按以下方式重寫模式(使用別名)。
case Some(req @ Request(_, _, _)) => new Response(405, "Method Not Allowed", req)
您不能在模式中使用代碼塊,而只能使用警惕( if ...
)。
有模式匹配的編譯器插件,例如豐富的模式匹配 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.