高效的 scala henrik engstrÖm typesafe 软件工程师 @h3nk3. ✦t✦t ypesafe...

68
高高高 Scala HENRIK ENGSTRÖM TYPESAFE 高高高高高 @h3nk3

Upload: donna-simpson

Post on 18-Jan-2016

332 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

高效的 ScalaHENRIK ENGSTRÖM

TYPESAFE 软件工程师@h3nk3

Page 2: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

✦ Typesafe 控制台技术负责人✦ Akka 团队荣誉会员

✦ 从 2010 年开始进行 Scala 编程

自我介绍✦ 从 1998 年开始做咨询 — 主要针对

Java

✦ 从 2011 年开始为 Typesafe 公司工作

✦ 阿森纳球迷 + 武术家

Page 3: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

关于 Typesafe

✦ Typesafe 平台‣ Play 、 Akka 、 Scala 、 Scala

IDE 、 Slick 、 SBT 等✦ 订阅✦ 培训和咨询

Page 4: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

议题✦ 基础知识✦ Scala 中的对象定位✦ 隐式✦ 类型✦ 集合✦ 模式匹配✦ 函数式编程

Page 5: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

基础知识

Page 6: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

// REPL = Read Eval Print Loop$ scala_home/bin/scalaWelcome to Scala version 2.10.0scala> println("Hello, world!")Hello, world!scala>

使用 REPL

Page 7: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

// Put JAR files in scala_home/lib to get access$ scala_home/bin/scalaWelcome to Scala version 2.10.0scala> import com.x.y.z.MyClassscala> val instance = new MyClassscala> instance.myMethod

REPL 和 JAR

Page 8: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

REPL 2013✦ IDE 工作表

- Scala IDE : 棒极了- IntelliJ : 很好

Page 9: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

// JAVAString result = null;if (z < 9) result = "<9" else result = ">=9";System.out.println("Result: " + result);// SCALAprintln("Result: " + if (z < 9) "<9" else ">=9"))

表达式与语句

Page 10: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

// What type is variable quiz?var x = 1val quiz = while (x < 10) { println("X is: " + x) x += 1}

语句突击测试 (Pop Quiz)

✦ Scala 中的所有表达式返回一个类型

Page 11: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

// Don’t tell the computer how to fishimport scala.collection.mutable.{HashSet => MHS}def findPeopleInCity(c: String, ppl: Seq[People]): Set[People] = { val found = new MHS[People]() for (p <- ppl) for (a <- p.address) if (a.city == c) found.put(p) found}

请注意无钓鱼说明!

Page 12: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

def findPeopleInCity(c: String, ppl: Seq[People]): Set[People] = { for { p <- ppl.toSet[People] a <- p.address if a.city == c } yield p}// SQL LIKE SYNTAX; FROM, WHERE, AND, SELECT

而只是点鱼

Page 13: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

// 1) Mutable code leads to cloning // 2) Cloning leads to performance degradation// => Mutable code leads to worse performanceclass Footballer { private var cars = Array[Car]() def setCars(c: Array[Car]): Unit = cars = c.clone def getCars: Array[Car] = cars.clone}

保持不可变

Page 14: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

// Safer code - use immutable collectionclass Footballer { private var cars = Vector.empty[Car] def setCars(c: Vector[Car]) = cars = c def getCars: Vector[Car] = cars}

保持不可变

Page 15: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

// Case classes make the class immutablescala> case class Car(brand: String)scala> case class Footballer(name: String, team: String, cars: Vector[Car] = Vector.empty)scala> var jw = new Footballer("Jack Wilshire", "Arsenal")Footballer(Jack Wilshire, Arsenal, Vector())scala> jw = jw.copy(cars = Vector(Car("Porsche")))Footballer(Jack Wilshire, Arsenal, Vector(Car(Porsche)))

Case 类 ftw

Page 16: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

不可变的优势✦ 简单均等✦ 简单散列代码✦ 无需锁定✦ 无防御性复制✦ Scala Case 类

‣ 自动均等 + 散列代码 (Murmur)

‣ 还有很多其他好处(例如复制)

Page 17: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

// Sometimes local mutability makes senseimport scala.collection.mutable.ArrayBufferclass MyClass { def theData: Seq[Int] = { val buffer = new ArrayBuffer[Int]() populateData(buffer) buffer.toSeq }}

局部可变性

Page 18: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

// A classic game of nulldef auth(usr: String, pwd: String): Privileges = if (usr == null || usr.isEmpty || pwd == null || pwd.isEmpty || !validCredentials(usr, pwd)) withPrivileges(Anonymous) else privilegesFor(usr)

使用选项

Page 19: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

def auth(usr: Option[String], pwd: Option[String]): Privileges = { val privileges: Option[Privileges] = { u <- usr p <- pwd if (!u.isEmpty && !p.isEmpty) if canAuthenticate(u, p) } yield privilegesFor(u) privileges getOrElse withPrivileges(Anonymous)}

使用选项

Page 20: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

对象定位

Page 21: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

trait SquareShape { val width: Int val height: Int val area: Int = width * height}class Rect(w: Int, h: Int) extends SquaredShape { override val width = w override val height = h}scala> val r1 = new Rectangle(1, 314)scala> r1.heightres0: Int = 314scala> r1.areares1: Int = 0

抽象成员的 val

Page 22: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

Scala 初始化顺序

✦ 摘自 Scala 规范(第 5.1 节)- http://www.scala-lang.org/docu/files/

ScalaReference.pdf

‣ 首先评估超类构建函数‣ 然后是模板线性化中的所有基类……

‣ 最后评估语句序列状态

Page 23: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

trait SquareShape { def width: Int def height: Int def area: Int = width * height}class Rect(w: Int, h: Int) extends SquaredShape { override val width = w override val height = h}// or even bettercase class Rect(width: Int, height: Int) extends SquaredShape

def is much better

Page 24: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

// Non-trivial return types should always be// annotated!def convert(x: Int) = x match { case 1 => 1.toChar case 2 => true case z => z.toByte}def convert(x: Int): AnyVal = x match {

为您的 API 加批注

Page 25: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

组合与继承

✦ 与继承相比,更偏好组合- 易于修改(例如 DI )

✦ 组合可在 Scala 中使用继承- 引向著名的“蛋糕”模式

Page 26: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

trait UserRepoComponent { def userLocator: UserLocator def userUpdater: UserUpdater trait UserLocator { def findAll: Vector[User] } trait UserUpdater { def save(user: User) }}

让我们来烘培一块“蛋糕”

Page 27: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

trait JPAUserRepoComponent extends UserRepoComponent { def em: EntityManager def userLocator = new JPAUserLocator(em) def userUpdater = new JPAUserUpdater(em) class JPAUserLocator(em: EntityManager) extends UserLocator { def findAll: Vector[User] = em.createQuery("from User", classOf[User]).getResultList.toVector } class JPAUserUpdater(em: EntityManager) extends UserUpdater { def save(user: User) = em.persist(user) }}

正在烘培

Page 28: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

trait UserServiceComponent { def userService: UserService trait UserService { def findAll: Vector[User] def save(user: User): Unit def checkStatusOf(user: User): String }}

服务层

Page 29: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

trait DefaultUserServiceComponent extends UserServiceComponent { this: UserRepositoryComponent => def userService = new DefaultUserService class DefaultUserService extends UserService { def findAll = userLocator.findAll def save(user: User) = userUpdater.save(user) def checkStatus(user: User) = s"User $user seems okay to me" }}

服务层实现

Page 30: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

object MyApplication extends Application { val compService = new DefaultUserServiceComponent with JPAUserRepositoryComponent { def em = Persistence.createEntityManagerFactory( "cakepattern").createEntityManager() } val service = compService.userService // use the service}

投入使用

Page 31: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

class MyTest extends WordSpec with MustMatchers with Mockito { trait MockedEntityManager { def em = mock[EntityManager] } "service" must { "return all users" in { val compService = new DefaultUserServiceComponent with JPAUserRepositoryComponent with MockedEntityManager // perform tests }}

进行测试

Page 32: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

隐式

Page 33: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

有何作用?

✦ 在特定上下文中移除样板代码‣ 编译时安全‣ 但是必须明确

Page 34: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

trait AutoRepository { def find(regId: String)(implicit dbId: DBId): Option[Car] def findAll(country: String)(implicit dbId: DBId): Seq[Car]}class DefaultAutoRepository extends AutoRepository { def find(regId: String)(implicit dbId: DBId): Option[Car] = { // ... } def findAll(country: String)(implicit dbId: DBId): Seq[Car] = { // ... }}

示例

Page 35: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

// Anti patternclass CarFinder { val dbId = DbId("Dealer1") val repo = new DefaultAutoRepository def getCar(regId: String): Option[Car] = repo.find(regId)(dbId) def listCars(country: String): Seq[Car] = repo.findAll(country)(dbId)}

示例(续)

Page 36: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

// Use implicits => much cleaner codeclass CarFinder { implicit val dbId = DbId("Dealer1") val repo = new DefaultAutoRepository def getCar(regId: String): Option[Car] = repo.find(regId) def listCars(country: String): Seq[Car] = repo.findAll(country)}

示例(续)

Page 37: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

编译器练习

✦ 隐式作用域‣ 词法: 当前作用域、显式导入、通配符

导入‣ 部分类型的伴生对象: 类型的伴生对象

、参数类型的伴生对象、嵌套类型的外部对象

✦ 编译时可能会消耗大量资源,应谨慎使用

Page 38: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

trait Logger { def log(msg: String) }object Logger { implicit object DefaultLogger extends Logger { def log(msg: String) = println("DL> " + msg) } def log(msg: String)(implicit logger: Logger) = { logger.log(msg) }}

隐式值

Page 39: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

scala> Logger.log("a small test")DL> a small testscala> class MyLogger extends Logger { def log(msg: String) = println("ML:>> " + msg) }scala> implicit def myLogger = new MyLoggerscala> Logger.log("another test")ML:>> another test

隐式值

Page 40: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

隐式智慧?

deech @deech调试 #scala 隐式内容如同在一个拥挤的房间中寻找 farter

Page 41: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

类型特性

Page 42: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

// "describes generic interfaces using type // parameters such that the implementations can// be created for any type"trait Encodable[T] { def from(t: T): String def to(s: String): T}object Encodable { implicit object IntEncoder extends Encodable[Int] { def from(i: Int): String = "int" + i def to(s: String): Int = s.substring(s.indexOf("int")+3, s.length).toInt }}

即,类型类

Page 43: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

class MyHandler { def convert[T](t: T)(implicit enc: Encodable[T]): String = enc.from(t) def convert[T](s: String)(implicit enc: Encodable[T]): T = enc.to(s)}scala> val myHandler = new MyHandlerscala> myHandler.convert(12345)res0: String = int12345scala> myHandler.convert(res0)res1: Int = 12345

使用示例

Page 44: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

scala> myHandler.convert(12345L)<console>:15: error: could not find implicit value for parameter encoder: Encodable[Long]scala> implicit object LongEnc extends Encodable[Long] { def from(l: Long): String = "long" + l def to(s: String): Long = s.substring(s.indexOf("long")+4, s.length).toLong }scala> myHandler.convert(12345L)

示例(续)

Page 45: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

集合

Page 46: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

集合概述

Page 47: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

不可变集合

Page 48: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

可变集合

Page 49: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

// It is absolutely *awesome*scala> val seq = Seq()scala> seq.++ ++: +: /: /:\ :+ :\ addString aggregate andThen apply applyOrElse

asInstanceOf canEqual collect collectFirst combinations companion compose contains containsSlice copyToArray copyToBuffer

corresponds count diff distinct drop dropRight dropWhile endsWith exists filter filterNot find

flatMap flatten fold foldLeft foldRight forall foreach genericBuilder groupBy grouped hasDefiniteSize head

headOption indexOf indexOfSlice indexWhere indices init inits intersect isDefinedAt isEmpty isInstanceOf

isTraversableAgain iterator last lastIndexOf lastIndexOfSlice lastIndexWhere lastOption length lengthCompare lift map max

maxBy min minBy mkString nonEmpty orElse padTo par partition patch permutations

prefixLength product reduce reduceLeft reduceLeftOption reduceOption reduceRight reduceRightOption repr reverse reverseIterator

reverseMap runWith sameElements scan scanLeft scanRight segmentLength seq size slice sliding sortBy

sortWith sorted span splitAt startsWith stringPrefix sum tail tails take takeRight takeWhile

to toArray toBuffer toIndexedSeq toIterable toIterator toList toMap toSeq toSet toStream toString

toTraversable toVector transpose union unzip unzip3 updated view withFilter zip zipAll zipWithIndex

了解和学习 API

Page 50: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

给 Java 开发人员的信息

✦ 使用 Vector 而不是 List

‣ 它更快‣ 它对内存的使用更高效

Page 51: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

模式匹配

Page 52: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

@scala.annotation.tailrecdef len[A](v: Vector[A], l: Int): Int = v match { case h :: t => len(t, l + 1) case Nil => l}scala> len(Vector("a","b","c","d")res0: Int = 4

FP 模式匹配

Page 53: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

def convertedAge(a: Animal): Int = a match { case Dog(name, age) => age * 7 case Human(_, age, _) => age case Walrus("Donny", age) => age / 10 case Walrus(name, age) if name == "Walter" => age case _ => 0}

提取并进行“ instanceof”判断

Page 54: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

相关成本

✦ 请注意,模式匹配实际上是 if - else if。

✦尝试在开始时放入最常见的发现,以减少跳跃次数

Page 55: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

函数式编程

Page 56: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

忠告

✦ 了解函数式编程的模式✦ 阅读有关 Functor 、 Applicative 和

Monad 的精彩文章‣ http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monad

s_in_pictures.html

✦查看 scalaz 了解 Scala 中 FP 的更多信息

Page 57: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

值和上下文23

(+8)

函数

31

2323

值和上下文

2323

Some[Int] 无

选项

上下文

Page 58: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

Functor

2323 (+8) 不适用!

2323

23 (+8) 31

3131

Some[Int] Some[Int]X (+8) X

无无

Page 59: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

trait Functor[F[_]] { def fmap[A,B](fa: F[A], f: A => B): F[B]}

Functor 定义

Page 60: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

def dblFunc(values: Vector[Int]): Vector[Int] = values map { _ * 2 } scala> dblFunc(Vector(1,2,3,4))res0: Vector(2,4,6,8)

Scala 中的 Functor

Page 61: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

Applicative

2323

Some[Int]

(+8(+8))

Some[f(x)]

23(+8)

3131

Some[Int]

Page 62: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

scala> Vector(1,2,3)res0: Vector[Int] = Vector(1,2,3)scala> List("A","B","C")res1: List[String] = List(A,B,C)scala> res0 zip res1res2: List[(Int,String)] = List((1,A),(2,B),(3,C))

Scala Applicative 示例

Page 63: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

Monad

2323

Some[Int]

23

isEven

2424

24

4848

24

2424

Some[Int]

isEven

*2无

Page 64: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

import scala.language.higherKindstrait Monad[M[_]] { def pure[A](a: A): M[A] def bind[A,B](ma: M[A])(f: A => M[B]): M[B]}

Monad 定义

Page 65: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

def even(number: Option[Int]): Option[Int] = for { n <- number if n % 2 == 0 } yield nscala> even(Some(22))res1: Option[Int] = Some(22)scala> even(Some(21))res2: Option[Int] = None

Scala Monad 示例

Page 66: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

总结

✦ FUNCTOR

- 将函数应用到包装值✦ APPLICATIVE

- 将包装函数应用到包装值✦ MONAD

- 将返回包装值的函数应用到包装值

Page 67: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

推荐的 Scala 书籍

Page 68: 高效的 Scala HENRIK ENGSTRÖM TYPESAFE 软件工程师 @h3nk3. ✦T✦T ypesafe 控制台技术负责人 ✦A✦A kka 团队荣誉会员 ✦从✦从 2010 年开始进行 Scala

EOF@h3nk3