Pragmatic Scala:Create Expressive, Concise, and Scalable Applications (读书笔记)

Pragmatic Scala:Create Expressive, Concise, and Scalable Applications

目录

From Java to Scala

  1. Tuple
    1. 使用t._1访问Tuple t的第一个成员(下标从1开始)
    2. val (firstName, lastName) = getPersonInfo(1)
  2. 变参
    1. def max(values: Int*) = values.foldLeft(values(0)) { Math.max }
    2. 将Array做变参展开:max(numbers: _*)(这估计又是编译期的语法糖?)
  3. 隐式参数(caller决定默认值,而非默认参数中callee决定)
    1. callee:def connectToNetwork(user: String)(implicit wifi: Wifi) { ... } //有点‘上下文’的意味?
    2. caller:implicit def officeNetwork = new Wifi("office-network") //What the fuck;
  4. Strings与多行字符串(从Perl中学来的?)
    1. scala.runtime.RichString?
    2. """ .... .... ... """
    3. val message = s"A discount of $discount% has been applied" //字符串插值,注意这里的s前缀
  5. Sensible Defaults
    1. 如果你不感兴趣可以不用捕获异常(将checked异常转换为runtime?)
    2. ()和.都是可选的(英文的代码风格)
  6. 运算符重载
  7. Scala Surprises for the Java Eyes
    1. 赋值的结果类型是Unit,所以不允许 a = b = 0; 连续赋值
    2. == 其实是 equals()
    3. 行尾;可选
    4. 避免显示return(Why?Scala的习俗?)
  8. Default Access Modifier

Objects

  1. 主构造器:
    1. class Person(val firstName: String, val lastName: String) { ... }
      1. var position: String = _ //转换为一个position() getter,和一个setter:position_=()
      2. 辅助:def this (firstName: String, lastName: String, pos: String) { this(firstName, lastName) ... }
      3. override def ...
  2. JavaBean
    1. import scala.beans.BeanProperty
    2. @BeanProperty var position: String = _ //修饰前缀
  3. 类型别名
    1. type Cop = PoliceOfficer //这是从ML/Haskell学习的吗
  4. Extending a Class
    1. class Car(override val id: Int, override val year: Int, var fuelLevel: Int) extends Vehicle(id, year) { //这里的override参数修饰很奇怪
  5. Parameterized Types(模板?)
    1. def echo2[T1, T2](input1: T1, input2: T2) = ...
  6. Singletons and Companions
    1. class Marker private(val color: String) { ... }
      1. object Marker { //这个同名的Marker类称为伴侣对象?
    2. object MarkerFactory { ... } //单例,object类
    3. Scala没有类static成员
  7. 枚举
    1. object Currency extends Enumeration {
      1. type Currency = Value
      2. val CNY, GBP, INR, JPY, NOK, PLN, SEK, USD = Value
  8. Package对象
    1. 与package同名的object类?

Types

  1. Scala不支持ArrayList[Int]赋值给ArrayList类型(相当于ArrayList[Nothing])的引用
  2. Any(superclass of all types)
    1. AnyVal
    2. AnyRef(直接映射到Java Object类):notify(), wait(), finalize()
  3. Nothing:bottomest type(可以理解为所有类型的并?T1 | T2 | ...)
  4. Optional[T]:Some[T] or None
  5. Either[T, S]
  6. Covariance and Contravariance(协变与逆变)
    1. 之所以不允许List<T>转换为List<Any>,是因为这样一来,就有可能串改List中的元素,导致所有元素不再是同一类型,==> covariance,反之允许List<Any>到List<T>则为contravariance
    2. 允许covariance:def playWithPets[T <: Pet](pets: Array[T]) = ...
      1. 这里的意思是说,只要输入容器中的元素类型是Pet的子类,函数都能够处理(即不要求元素是同一子类类型)
      2. Pet定义了T的‘上界’(类型层次中最上面的是Any)
    3. 支持contravariance(下界):
      1. def copyPets[S, D >: S](fromPets: Array[S], toPets: Array[D]) = ... //看来逆变用于定义from/to类型约束
    4. class MyList[+T] //允许协变;允许T或其基类
      1. -T
  7. 隐式类型转换
    1. Implicit Functions(相当于C++里面的operator T类型转换函数): 在一个object类中implicit def即可
    2. Implicit Classes
  8. Value类*
  9. 使用隐式转换(有点意思,Ruby里的Helper类扩展方法)
    1. implicit class Interpolator(val context: StringContext) extends AnyVal { ...

Function Values and Closures

  1. (args, ...) => ...
  2. Currying:def foo(a: Int)(b: Int)(c:Int) = {}
    1. val total = (0 /: arr) { (sum, elem) => sum + elem }
    2. val total = (0 /: arr) { _ + _ } (占位参数)
    3. val largest = (Integer.MIN_VALUE /: arr) { Math.max }
  3. 部分应用的函数(不同于Currying?)
    1. val logWithDateBound = log(date, _ : String) //内部封装了一个新的函数对象
  4. Closures
    1. var product = 1; loopThrough(5) { product *= _ }
  5. Execute Around Method

Traits

  1. 实例trait:var a = new A() with T;
  2. abstract override:子trait实现基trait里定义的抽象方法接口?

Collections

  1. Set、List、Map
  2. immutable
  3.  ::: list prepend操作
  4. method /:() is equivalent to foldLeft() and \:() to foldRight()
    1. val total2 = (0 /: feeds) { (total, feed) => total + feed.length }
  5. 操作符重载:
    1. unary_+() unary_-() unary_~() unary_!()
  6. for生成器:for([pattern <- generator; definition*]+; filter*) [yield] expression

模式匹配与正则表达式

  1. input match { ... case _ => ... } //注意,Map()里使用->表示key-value映射
    1. case List("red", "blue", _*) => //忽略剩余元素
    2. case List("apple", "orange", otherFruits @ _*) => //命名剩余元素
    3. case (a: Int, b: Int) =>
    4. case msg : Int if (msg > 1000000) =>
    5. case this.max => //不加this.就将创建一个模式变量?
      1. case `max` => //引用scope内的常量?
      2. case MAX => //使用大写,这也不会创建模式变量
  2. case类(这有点像Clojure里面的多重派发)
    1. 必须extends同一个trait?
    2. 调用时传递case类实例需要加(),否则是一个Function0 trait对象
  3. Extractors与正则表达式
    1. unapply()(输入就是match,返回Extractor的实例)
    2. RE作为提取器:
      1. val GoogStock = """^GOOG:(\d*\.\d+)""".r
      2. case GoogStock(price) => ...
  4. _
    1. var msg : String = _ //初始化为默认null
    2. 函数命名中作为运算符的前缀
    3. val square = Math.pow(_: Int, 2)

处理异常

  1. Java的异常catch的顺序敏感,而Scala使用模式匹配的风格(它该不会是先捕获异常基类,然后再进行模式匹配的吧?)

递归

  1. TCO
    1. Java字节码:invokeSpecial --> goto?
    2. @scala.annotation.tailrec //只能处理直接递归;
  2. Trampoline:处理间接递归
    1. import scala.util.control.TailCalls._
    2. 用done()和tailcall()封装原来的f<-->g互相递归调用 //看起来很神奇啊?

惰性求值与并行集合

  1. lazy val perform = expensiveComputation()
  2. You can turn a strict collection into lazy using the view() method
    1. 有点数据库中‘物化视图’的感觉
  3. Stream
    1. #:: (::的lazy版本)
    2. println(generate(25).takeWhile{ _ < 40 }.force)
  4. 并行集合
    1. par()与seq()
      1. timeSample { cities => (cities.par map getWeatherData).toList }
    2. Furthermore, you shouldn't use parallel collections if the operations are nonassociative.

Actors

  1. import akka.actor._
  2. class HollywoodActor() extends Actor {
    1. def receive = { case message => ... //隐式参数???
  3. val system = ActorSystem("sample")
    1. val depp = system.actorOf(Props[HollywoodActor]) //见鬼,几乎每一个特性都有新的语法(这一点上远没有Erlang纯粹)
    2. depp ! "Wonka"
  4. 使用建议
    1. Rely more on stateless actors instead of stateful actors
    2. Keep the processing in the receive() method really fast
    3. Ensure the messages passed between actors are immutable objects
    4. As much as possible, avoid using ask()(2路同步通信?)

Java互操作

  1. 避免Java中的名字与Scala关键字冲突:val theYield2 = investment.`yield`()

创建应用

  1. import scala.io.Source => Source.fromFile("ReadingFile.scala").foreach { print }
  2. val xmlFragment = <symbols> ...
    1. var symbolNodes = xmlFragment \ "symbol" //XPath选择器?
    2. case <units>{numberOfUnits}</units> => ...
  3. val data = scala.io.Source.fromURL(url).mkString

单元测试

  1. JUnit:略
  2. Using ScalaTest
    1. "a list" should "be empty on create" in new EmptyArrayList { list.size should be (0) } //变态的语法
  3. Using Mockito
    1. "score" should "return 0 for an empty word" in { withWordScorer { wordScorer => wordScorer.score("") should be (0) } }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值