匹配使用case 類:
case classes是用於模式比對與case 運算式指定類。這些都是標準類具有特殊修飾:case。下面是一個簡單的模式使用case class匹配樣本:
object Test {
def main(args: Array[String]) {
val alice = new Person("Alice", 25)
val bob = new Person("Bob", 32)
val charlie = new Person("Charlie", 32)
for (person <- List(alice, bob, charlie)) {
person match {
case Person("Alice", 25) => println("Hi Alice!")
case Person("Bob", 32) => println("Hi Bob!")
case Person(name, age) =>
println("Age: " + age + " year, name: " + name + "?")
}
}
}
// case class, empty one.
case class Person(name: String, age: Int)
}
當上述代碼被編譯和執行時,它產生了以下結果:
C:/>scalac Test.scala
C:/>scala Test
Hi Alice!
Hi Bob!
Age: 32 year, name: Charlie?
C:/>
增加 case 關鍵字使編譯器自動添加了許多實用的功能。關鍵字建議與模式比對的情況下運算式的關聯。
首先,編譯器會自動轉換的建構函式的參數為不可變的欄位(vals)。val關鍵字是可選的。如果想可變欄位,使用var關鍵字。因此,建構函式的參數列表現在更短。
其次,編譯器自動實現equals, hashCode, 和toString方法的類,它使用指定為建構函式參數的欄位。因此,不再需要自己的toString方法。
最後,還消失Person類的主體部分,因為沒有需要定義的方法。
Scala支援通過Regex類的scala.util.matching封裝Regex。讓我們看看一個例子,我們將嘗試從Scala中一個語句中找出單詞:
import scala.util.matching.Regex
object Test {
def main(args: Array[String]) {
val pattern = "Scala".r
val str = "Scala is Scalable and cool"
println(pattern findFirstIn str)
}
}
當上述代碼被編譯和執行時,它產生了以下結果:
C:/>scalac Test.scala
C:/>scala Test
Some(Scala)
C:/>
我們建立一個字串,並調用r()方法就可以了。Scala中字串隱式轉換為一個RichString並調用該方法來獲得Regex的一個執行個體。找到第 一個Regex匹配,只需調用findFirstIn()方法。而非只找到第一次出現。如果想找到匹配的單詞的所有事件,可以使用findAllIn() 方法,並在情況下,有目標字串中使用多個Scala的單詞,這將返回所有匹配的集合單詞。
可以使用mkString()方法來串連所產生的服務,可以使用管道(|)搜尋Scala中小型和資本的情況下,使用Regex構造來代替或r()方法建立一個模式如下:
import scala.util.matching.Regex
object Test {
def main(args: Array[String]) {
val pattern = new Regex("(S|s)cala")
val str = "Scala is scalable and cool"
println((pattern findAllIn str).mkString(","))
}
}
當上述代碼被編譯和執行時,它產生了以下結果:
C:/>scalac Test.scala
C:/>scala Test
Scala,scala
C:/>
如果想更換匹配的文本,可以使用replaceFirstIn()以取代第一個匹配項或replaceAllIn(),以取代所有出現如下:
object Test {
def main(args: Array[String]) {
val pattern = "(S|s)cala".r
val str = "Scala is scalable and cool"
println(pattern replaceFirstIn(str, "Java"))
}
}
當上述代碼被編譯和執行時,它產生了以下結果:
C:/>scalac Test.scala
C:/>scala Test
Java is scalable and cool
C:/>
形成Regex:
Scala繼承了Java,這反過來又繼承了大部分的Perl的功能,它的Regex文法。這裡只是一些例子,應該是足夠的說明:
下面是表,列出了所有的Regex元字元的文法可用在Java中:
子運算式
匹配
^
匹配行頭
$
匹配行尾
.
匹配除分行符號任何單個字元。用m選項也允許使之匹配分行符號。
[...]
匹配括弧內任何單個字元。
[^...]
匹配任何單個字元不是在括弧中
\A
整個字串的開始
\z
整個字串結束
\Z
最終,除了允許的最後行結束整個字串。
re*
匹配0或多次出現前面運算式。
re+
匹配1個或多個的先前東西
re?
匹配0或1發生前運算式。
re{ n}
精確匹配n個前面運算式的數量。
re{ n,}
匹配n或多次出現前面的表達。
re{ n, m}
至少匹配n和在前面的表現最為m次出現。
a|b
匹配a或b。
(re)
組Regex並記住匹配的文本。
(?: re)
組Regex而不記住匹配的文本。
(?> re)
匹配獨立模式而不反向追蹤。
\w
匹配單詞字元。
\W
匹配非單詞字元。
\s
匹配空白。相當於 [ f].
\S
匹配非空白。
\d
匹配數字。相當於 [0-9].
\D
匹配非數字。
\A
匹配開始的字串。
\Z
匹配字串的結尾。如果一個分行符號存在,它只是換行之前匹配。
\z
匹配字串的結尾。
\G
匹配點,最後一次匹配結束。
\n
反向引用以擷取的群組編號 "n"
\b
匹配單詞邊界之外時,括弧內。匹配退格(0×08)括弧裡面。
\B
匹配非單詞邊界。
\n, \t, etc.
匹配分行符號,斷行符號,定位字元等
\Q
轉義(引用)所有字元為 \E
\E
尾部引用開始 \Q Regex的例子:
樣本
描述
.
匹配除了分行符號的任何字元
[Rr]uby
匹配 "Ruby" 或"ruby"
rub[ye]
匹配"ruby" 或 "rube"
[aeiou]
匹配任何一個小寫母音
[0-9]
匹配任何數字;同 [0123456789]
[a-z]
匹配任意小寫ASCII字母
[A-Z]
匹配任意大寫ASCII字母
[a-zA-Z0-9]
匹配任何上述
[^aeiou]
匹配母音以外的任何一個小寫字元
[^0-9]
匹配數字以外的任何其他
\d
匹配一個數字: [0-9]
\D
匹配一個非數字: [^0-9]
\s
匹配一個空白字元: [ f]
\S
匹配非空白: [^ f]
\w
匹配一個字元: [A-Za-z0-9_]
\W
匹配一個非單詞字元: [^A-Za-z0-9_]
ruby?
匹配 "rub" or "ruby": the y is optional
ruby*
匹配 "rub" plus 0 or more ys
ruby+
匹配 "rub" plus 1 or more ys
\d{3}
匹配只有 3 個數字
\d{3,}
匹配 3 個或多個數字
\d{3,5}
匹配3, 4, 或5 個數字
\D\d+
不分組: + repeats \d
(\D\d)+/
分組: + repeats \Dd 對
([Rr]uby(, )?)+
匹配 "Ruby", "Ruby, ruby, ruby", 等.
需要注意的是每一個反斜線上述字串中出現兩次。這是因為在Java和Scala一個反斜線是一個逸出字元的字串,而不是一個一般字元顯示出來的字串。所以不是.. 需要寫.\ 。得到的字串中的一個反斜線。請查看下面的例子:
import scala.util.matching.Regex
object Test {
def main(args: Array[String]) {
val pattern = new Regex("abl[ae]\d+")
val str = "ablaw is able1 and cool"
println((pattern findAllIn str).mkString(","))
}
}
當上述代碼被編譯和執行時,它產生了以下結果:
C:/>scalac Test.scala
C:/>scala Test
able1
C:/>
Scala的異常的工作像許多其他語言,如Java異常。而不是正常方式返回的值,方法可以通過拋出一個異常終止。然而,Scala實際上並沒有檢查異常。
當要處理異常,那麼可使用try{...}catch{...} 塊,就像在Java中除了catch塊採用匹配識別和處理異常。 拋出異常:
拋出一個異常看起來類似於Java。建立一個異常對象,然後使用throw關鍵字把它拋出:
throw new IllegalArgumentException
捕獲異常:
Scala中try/catch在一個單獨的塊捕捉任何異常,然後使用case塊進行模式比對,如下圖所示:
import java.io.FileReader
import java.io.FileNotFoundException
import java.io.IOException
object Test {
def main(args: Array[String]) {
try {
val f = new FileReader("input.txt")
} catch {
case ex: FileNotFoundException =>{
println("Missing file exception")
}
case ex: IOException => {
println("IO Exception")
}
}
}
}
當上述代碼被編譯和執行時,它產生了以下結果:
C:/>scalac Test.scala
C:/>scala Test
Missing file exception
C:/>
這種try-catch表達的行為在其他語言處理異常是一樣的。body是執行體,如果它拋出一個異常,每個catch子句都依次嘗試捕獲。 finally子句:
如果想知道引起一些代碼是如何表達的終止執行,可以用一個finally子句包住一個運算式,finally塊什麼時候都會執行。
import java.io.FileReader
import java.io.FileNotFoundException
import java.io.IOException
object Test {
def main(args: Array[String]) {
try {
val f = new FileReader("input.txt")
} catch {
case ex: FileNotFoundException => {
println("Missing file exception")
}
case ex: IOException => {
println("IO Exception")
}
} finally {
println("Exiting finally...")
}
}
}
當上述代碼被編譯和執行時,它產生了以下結果:
C:/>scalac Test.scala
C:/>scala Test
Missing file exception
Exiting finally...
C:/>
提取器在Scala中是一個對象,有一個叫非應用作為其成員的一種方法。即不應用方法的目的是要匹配的值,並把它拆開。通常,提取對象還限定了雙方法申請構建值,但是這不是必需的。
下面的例子顯示電子郵件地址的提取器對象:
object Test {
def main(args: Array[String]) {
println ("Apply method : " + apply("Zara", "gmail.com"));
println ("Unapply method : " + unapply("Zara@gmail.com"));
println ("Unapply method : " + unapply("Zara Ali"));
}
// The injection method (optional)
def apply(user: String, domain: String) = {
user +"@"+ domain
}
// The extraction method (mandatory)
def unapply(str: String): Option[(String, String)] = {
val parts = str split "@"
if (parts.length == 2){
Some(parts(0), parts(1))
}else{
None
}
}
}
這個對象定義了 apply 和unapply 方法。該apply 方法具有相同的含義:它原來的測試為可以被應用到的參數在括弧中的方法所應用的相同的方式的對象。所以,可以寫為Test("Zara", "gmail.com") 來構造字串“Zara@gmail.com”。
unapply方法使測試類別成為一個提取器並反轉應用的構造過程。應用需要兩個字串,並形成了一個電子郵件地址以找到它們,非應用unapply需要一個電子郵件地址,並可能返回兩個字串:使用者和地址的網域名稱。
unapply還必須處理中給定的字串不是一個電子郵件地址的情況。這就是為什麼unapply返回一個選項型過對字串。其結果要麼是一些(使用者域) 如果字串str使用給定電子郵件地址的使用者和域的部分,或None,如果str不是一個電子郵件地址。下面是一些例子:
unapply("Zara@gmail.com") equals Some("Zara", "gmail.com")
unapply("Zara Ali") equals None
讓我們編譯和運行上面的程式,這將產生以下結果:
C:/>scalac Test.scala
C:/>scala Test
Apply method : Zara@gmail.com
Unapply method : Some((Zara,gmail.com))
Unapply method : None
C:/>
from: http://www.yiibai.com/scala/scala_basic_syntax.html