Programming Scala
CHAPTER 3
Rounding Out the Essentials
1. Operator? Operator?
所有的操作符都是方法
1 + 2 // 其实就是 (1).+(2)
infix notation 中缀表示法
当方法只有一个参数时,可以把.和括号去掉。
postfix notation 后缀表示法
当方法没有参数时,可以把.去掉。
"abc".reverse // "abc" reverse
使用操作符都是方法的特性,可以写出更简洁易懂的代码。但不要滥用,反而导致难以理解。
2. Methods Without Parentheses and Dots
Precedence Rules
先*/,后+-。其他不太容易记住,用()不容易出错。
3. Domain-Specific Languages
Scala丰富灵活的语法,很适合编写DSL
4. Scala if Statements
if 语言是表达式,它有返回值
val t = if(...) {
...
} else if(...) {
...
} else {
...
}
5. Scala for Comprehensions
Scala中的for要比Java强大很多
val dogBreeds = List("Doberman", "Yorkshire Terrier", "Dachshund", "Scottish Terrier", "Great Dane", "Portuguese Water Dog")
for (breed <- dogBreeds) println(breed)
过滤
for (breed <- dogBreeds
if breed.contains("Terrier");
if !breed.startsWith("Yorkshire")
) println(breed)
Yielding
val filteredBreeds = for { //这里使用的是 {}
breed <- dogBreeds
if breed.contains("Terrier") //没有;
if !breed.startsWith("Yorkshire")
} yield breed
6. Other Looping Constructs
Scala While Loops
while (...) {
...
}
Scala do-while Loops
do {
...
} while (...)
Generator Expressions
for (i <- 1 to 10) println(i) // <-是生成器操作符。1 to 10就是(1).to(10), 生成一个Range
scala2.7中没有break和continue
7. Conditional Operators
&& || > >= < <= == !=
8. Pattern Matching
match类似于java中的case, 但功能远比case强大。
简单的例子
val bools = List(true, false)
for (bool <- bools) {
bool match {
case true => println("heads")
case false => println("tails")
case _ => println("something other than heads or tails (yikes!)") // same as default
}
}
Variables in Matches
import scala.util.Random
val randomInt = new Random().nextInt(10)
randomInt match {
case 7 => println("lucky seven!")
case otherNumber => println("boo, got boring ol' " + otherNumber)
}
Matching on Type
val sundries = List(23, "Hello", 8.5, 'q')
for (sundry <- sundries) {
sundry match {
case i: Int => println("got an Integer: " + i)
case s: String => println("got a String: " + s)
case f: Double => println("got a Double: " + f)
case other => println("got something else: " + other)
}
}
Matching on Sequences
val willWork = List(1, 3, 23, 90)
val willNotWork = List(4, 18, 52)
val empty = List()
for (l <- List(willWork, willNotWork, empty)) {
l match {
case List(_, 3, _, _) => println("Four elements, with the 2nd being '3'.")
case List(_*) => println("Any other list with 0 or more elements.")
}
}
Matching on Tuples (and Guards)
val tupA = ("Good", "Morning!")
val tupB = ("Guten", "Tag!")
for (tup <- List(tupA, tupB)) {
tup match {
case (thingOne, thingTwo) if thingOne == "Good" => //if condition is a guard
println("A two-tuple starting with 'Good'.")
case (thingOne, thingTwo) =>
println("This has two things: " + thingOne + " and " + thingTwo)
}
}
Matching on Case Classes
与Actors配合使用时非常有用
case class Person(name: String, age: Int) //case class
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("Who are you, " + age + " year-old person named " + name + "?")
}
}
Matching on Regular Expressions
val BookExtractorRE = """Book: title=([^,]+),/s+authors=(.+)""".r // Calling .r on a string turns it into a regex
val MagazineExtractorRE = """Magazine: title=([^,]+),/s+issue=(.+)""".r
val catalog = List(
"Book: title=Programming Scala, authors=Dean Wampler, Alex Payne",
"Magazine: title=The New Yorker, issue=January 2009",
"Book: title=War and Peace, authors=Leo Tolstoy",
"Magazine: title=The Atlantic, issue=February 2009",
"BadData: text=Who put this here??"
)
for (item <- catalog) {
item match {
case BookExtractorRE(title, authors) =>
println("Book /"" + title + "/", written by " + authors)
case MagazineExtractorRE(title, issue) =>
println("Magazine /"" + title + "/", issue " + issue)
case entry => println("Unrecognized entry: " + entry)
}
}
Binding Nested Variables in Case Clauses
class Role
case object Manager extends Role
case object Developer extends Role
case class Person(name: String, age: Int, role: Role)
val alice = new Person("Alice", 25, Developer)
val bob = new Person("Bob", 32, Manager)
val charlie = new Person("Charlie", 32, Developer)
for (item <- Map(1 -> alice, 2 -> bob, 3 -> charlie)) {
item match {
case (id, p @ Person(_, _, Manager)) => format("%s is overpaid./n", p)
case (id, p @ Person(_, _, _)) => format("%s is underpaid./n", p)
}
}
Using try, catch, and finally Clauses
Scala没有checked exceptions。
try {
...
} catch {
case e: NullPointerException => println("...")
case unknown => println("Unknown exception " + unknown)
} finally {
....
}
Concluding Remarks on Pattern Matching
注意要使用在合适的地方。
9. Enumerations
object Breed extends Enumeration {
val doberman = Value("Doberman Pinscher")
val yorkie = Value("Yorkshire Terrier")
val scottie = Value("Scottish Terrier")
val dane = Value("Great Dane")
val portie = Value("Portuguese Water Dog")
}
// print a list of breeds and their IDs
println("ID/tBreed")
for (breed <- Breed) println(breed.id + "/t" + breed)
// print a list of Terrier breeds
println("/nJust Terriers:")
Breed.filter(_.toString.endsWith("Terrier")).foreach(println)