# Scala教程之:函数式的Scala

04/11 20:53

### 文章目录

Scala是一门函数式语言，接下来我们会讲一下几个概念：

• 高阶函数
• 方法嵌套
• 多参数列表
• 样例类
• 模式匹配
• 单例对象
• 正则表达式模式
• For表达式

## 高阶函数

``````val salaries = Seq(20000, 70000, 40000)
val doubleSalary = (x: Int) => x * 2
val newSalaries = salaries.map(doubleSalary) // List(40000, 140000, 80000)``````

map接收一个函数为参数。所以map是一个高阶函数，map也可直接接收一个匿名函数，如下所示：

``````val salaries = Seq(20000, 70000, 40000)
val newSalaries = salaries.map(x => x * 2) // List(40000, 140000, 80000)``````

``````val salaries = Seq(20000, 70000, 40000)
val newSalaries = salaries.map(_ * 2)``````

### 强制转换方法为函数

``````case class WeeklyWeatherForecast(temperatures: Seq[Double]) {

private def convertCtoF(temp: Double) = temp * 1.8 + 32

def forecastInFahrenheit: Seq[Double] = temperatures.map(convertCtoF) // <-- passing the method convertCtoF
}``````

## 方法嵌套

``````def factorial(x: Int): Int = {
def fact(x: Int, accumulator: Int): Int = {
if (x <= 1) accumulator
else fact(x - 1, x * accumulator)
}
fact(x, 1)
}

println("Factorial of 2: " + factorial(2))
println("Factorial of 3: " + factorial(3))``````

``````Factorial of 2: 2
Factorial of 3: 6``````

## 多参数列表

Scala和java不同的是他可以定义多个参数列表，下面是一个例子：

``def foldLeft[B](z: B)(op: (B, A) => B): B``

``````val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val res = numbers.foldLeft(0)((m, n) => m + n)
print(res) // 55``````

``numbers.foldLeft(0)(_ + _)``

## 样例类

case class主要用于不可变的数据。他们和普通类几乎是一样的。

``````case class Book(isbn: String)

val frankenstein = Book("978-0486282114")``````

``````case class Message(sender: String, recipient: String, body: String)
val message1 = Message("guillaume@quebec.ca", "jorge@catalonia.es", "Ça va ?")

println(message1.sender)  // prints guillaume@quebec.ca
message1.sender = "travis@washington.us"  // this line does not compile``````

### 比较

case class的比较是按值比较的，而不是按引用：

``````case class Message(sender: String, recipient: String, body: String)

val message2 = Message("jorge@catalonia.es", "guillaume@quebec.ca", "Com va?")
val message3 = Message("jorge@catalonia.es", "guillaume@quebec.ca", "Com va?")
val messagesAreTheSame = message2 == message3  // true``````

### 拷贝

``````case class Message(sender: String, recipient: String, body: String)
val message4 = Message("julien@bretagne.fr", "travis@washington.us", "Me zo o komz gant ma amezeg")
val message5 = message4.copy(sender = message4.recipient, recipient = "claire@bourgogne.fr")
message5.sender  // travis@washington.us
message5.recipient // claire@bourgogne.fr
message5.body  // "Me zo o komz gant ma amezeg"``````

## 模式匹配

scala中使用match关键字和case来做模式匹配，类似java中的switch。

``````import scala.util.Random

val x: Int = Random.nextInt(10)

x match {
case 0 => "zero"
case 1 => "one"
case 2 => "two"
case _ => "other"
}``````

match表达式是有值的，如下所示：

``````def matchTest(x: Int): String = x match {
case 1 => "one"
case 2 => "two"
case _ => "other"
}
matchTest(3)  // other
matchTest(1)  // one``````

case也可以匹配case class， 如下所示：

``````abstract class Notification

case class Email(sender: String, title: String, body: String) extends Notification

case class SMS(caller: String, message: String) extends Notification

case Email(sender, title, _) =>
s"You got an email from \$sender with title: \$title"
case SMS(number, message) =>
s"You got an SMS from \$number! Message: \$message"
}
}
val someSms = SMS("12345", "Are you there?")
val someVoiceRecording = VoiceRecording("Tom", "voicerecording.org/id/123")

println(showNotification(someSms))  // prints You got an SMS from 12345! Message: Are you there?

case后面还可以加if语句，我们称之为模式守卫。

``````def showImportantNotification(notification: Notification, importantPeopleInfo: Seq[String]): String = {
case Email(sender, _, _) if importantPeopleInfo.contains(sender) =>
"You got an email from special someone!"
case SMS(number, _) if importantPeopleInfo.contains(number) =>
"You got an SMS from special someone!"
case other =>
}
}``````

``````abstract class Device
case class Phone(model: String) extends Device {
def screenOff = "Turning screen off"
}
case class Computer(model: String) extends Device {
def screenSaverOn = "Turning screen saver on..."
}

def goIdle(device: Device) = device match {
case p: Phone => p.screenOff
case c: Computer => c.screenSaverOn
}``````

### 密封类

``````sealed abstract class Furniture
case class Couch() extends Furniture
case class Chair() extends Furniture

def findPlaceToSit(piece: Furniture): String = piece match {
case a: Couch => "Lie on the couch"
case b: Chair => "Sit on the chair"
}``````

## 单例对象

``````package logging

object Logger {
def info(message: String): Unit = println(s"INFO: \$message")
}``````

``````import logging.Logger.info

class Project(name: String, daysToComplete: Int)

class Test {
val project1 = new Project("TPS Reports", 1)
val project2 = new Project("Website redesign", 5)
info("Created projects")  // Prints "INFO: Created projects"
}``````

### 伴生对象

``````import scala.math._

import Circle._
}

object Circle {
}

val circle1 = Circle(5.0)

circle1.area``````

## 正则表达式模式

``````import scala.util.matching.Regex

val numberPattern: Regex = "[0-9]".r

case None => println("Password must contain a number")
}``````

``````import scala.util.matching.Regex

val keyValPattern: Regex = "([0-9a-zA-Z-#() ]+): ([0-9a-zA-Z-#() ]+)".r

val input: String =
"""background-color: #A03300;
|background-position: top center;
|background-repeat: repeat-x;
|background-size: 2160px 108px;
|margin: 0;
|height: 108px;
|width: 100%;""".stripMargin

for (patternMatch <- keyValPattern.findAllMatchIn(input))
println(s"key: \${patternMatch.group(1)} value: \${patternMatch.group(2)}")``````

## For表达式

``````case class User(name: String, age: Int)

val userBase = List(User("Travis", 28),
User("Kelly", 33),
User("Jennifer", 44),
User("Dennis", 23))

val twentySomethings = for (user <- userBase if (user.age >=20 && user.age < 30))
yield user.name  // i.e. add this to a list

twentySomethings.foreach(name => println(name))  // prints Travis Dennis``````

``````def foo(n: Int, v: Int) =
for (i <- 0 until n;
j <- i until n if i + j == v)
yield (i, j)

foo(10, 10) foreach {
case (i, j) =>
println(s"(\$i, \$j) ")  // prints (1, 9) (2, 8) (3, 7) (4, 6) (5, 5)
}``````

1
0 收藏

0 评论
0 收藏
1