Notes of Programming Scala: Type Less, Do more

简介

本章主要介绍Scala简介灵活的代码语法,如何组织文件与包,如何导入其他类型,变量方法与声明,以及常用的数据类型和语法惯例.

分号

与其他语言比如Java或Python相比,用于判断表达式的结束的分号;,在Scala中可以省略.如果需要在一行中编写多个表达式,仍然可以使用分号隔开.

变量声明

使用两种方式来声明变量,valvar,前者表示一个不可变的变量,后者表示一个可变变量,即声明后就不能再进行赋值操作.

如果在构造函数中使用这两个关键字,这时候变量是该类的一个属性,val表示该属性不可变,var则表示可变.

为了减少可变性带来的BUG应该尽量使用不可变的val.

Range

用于生成一个序列,创建时需要提供一个起始值和上限,一个可选的步长,如果步长为负值,则从上限值开始生成一个反向的序列.

10 to 1 by -3

'a' to 'g' by 3

偏函数

PartialFunctionFunction的一个子类.

偏函数之所以被称为,是因为并不处理所有可能的输入,而是只处理那些能与至少一个case匹配的输入.在偏函数中只能使用case语句,必须使用大括号包围.

如果调用偏函数时,输入与所有语句都不匹配则会抛出MatchError运行时错误.使用偏函数的isDefinedAt方法测试特定输入是否与该偏函数匹配(返回一个布尔值),以避免运行时错误.

偏函数可以使用链式连接,pf1 orElse pf2 orElse pf3,第一个不匹配则会继续尝试匹配下一个,均不匹配时抛出MatchError错误.

实例:

// 定义偏函数
val pf1:PartialFunction[Any,String] = { case s:String => "YES"}     // 仅匹配字符串
val pf2:PartialFunction[Any,String] = { case d:Double => "YES"}     // 仅匹配Double

// 组合偏函数
val pf = pf1 orElse pf2

// 定义一个辅助函数,用于捕获偏函数中的异常
def tryPF(x:Any, f: PartialFunction[Any, String]): String = 
  try {
    f(x).toString
  }
  catch {
    case _: MatchError => "ERROR!"
  }

// 定义一个辅助函数,使用isDefinedAt判断偏函数是否能处理指定的值
def d(x: Any, f: PartialFunction[Any,String]) = 
  f.isDefinedAt(x)                                          // 返回一个布尔值,true表示该偏函数能够匹配给定的值

实例:

case class PhoneExt(name: String, ext: Int)

val extensions = List(PhoneExt("steve", 100), PhoneExt("robey", 200))

extensions.filter { case PhoneExt(name, extension) => extension < 200 }
// res0: List[PhoneExt] = List(PhoneExt(steve,100))

filter方法可以接受一个Function,而提供的是一个(PhoneExt) => Boolean的偏函数,属于Function的子类.等效于:

val filterByExtension[PhoneExt,Boolean] = { case PhoneExt(name, extension) => extension < 200 }