2015-05-13 146 views
1

我開始學習偉大的Scala語言ANG有一個關於「深」模式匹配斯卡拉:有case類和代碼塊模式匹配選項

我有一個簡單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.getcase聲明以獲取操作Request對象。由於case聲明匹配,它是否安全?我覺得有點難看。是否可以從Some「打開」Request對象,但仍能匹配Request類字段?

如果我想要一個case內部複雜的計算與局部變量,等...我可以使用後case語句{}塊?我使用官方Scala插件的IntelliJ Idea,並突出顯示了我的括號,並建議將其刪除。

如果可能的話,是否將比賽中的比賽包含在比賽中?

... 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

對於你的問題的第一部分,你能說出你對陣與@值:

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 Specifications8.1.3:圖案粘合劑):

模式綁定器x @ p由模式變量x和模式p組成。 變量x的類型是模式p的靜態類型T.如果 的運行時類型v也是T的一個實例,並且它將 變量名稱綁定到該值,此 模式匹配與模式p匹配的任何值v。

但是,你不需要在你的例子:因爲你不反對任何匹配有關Request只是它的存在,你可以這樣做:

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

對於第二部分,你可以嵌套match es。 Intellij建議刪除大括號的原因是它們是不必要的:關鍵字case足以知道前面的case已完成。

至於這是否是一種好的做法,顯然取決於情況,但我可能會嘗試將代碼重構爲更小的塊。

0

您可以重寫模式如下(帶別名)。

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

你不能在模式中使用代碼塊,只能防範(if ...)。

有模式匹配的編譯器插件,如rich pattern matching

+0

你能指點我的文檔頁面在哪裏解釋'@'?我嘗試谷歌它 – dmzkrsk

+0

別名是scala語法的一部分(內置,而不是從一個插件):'case aliasA @ PatExpr(_,subAlias @ PatExpr(_,_))=> println(s「$ aliasA/$ subAlias 「)' – cchantep