本速查表可以用于快速地查找 Scala 语法结构
入门
介绍
函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| def f(x: Int) = { x*x } def f(x: Int) { x*x }
def f(x: Any) = println(x) def f(x) = println(x)
type R = Double def f(x: R) vs. def f(x: => R) (x:R) => x*x (1 to 5).map(_*2) vs. (1 to 5).reduceLeft( _+_ ) (1 to 5).map( x => x*x )
(1 to 5).map(2*) (1 to 5).map(*2)
(1 to 5).map { x => val y=x*2; println(y); y } (1 to 5) filter {_%2 == 0} map {_*2}
def compose(g:R=>R, h:R=>R) = (x:R) => g(h(x)) val f = compose({_*2}, {_-1})
val zscore = (mean:R, sd:R) => (x:R) => (x-mean)/sd def zscore(mean:R, sd:R) = (x:R) => (x-mean)/sd def zscore(mean:R, sd:R)(x:R) = (x-mean)/sd
val normer = zscore(7, 0.4) _ def mapmake[T](g:T=>T)(seq: List[T]) = seq.map(g)
5.+(3); 5 + 3 (1 to 5) map (_*2) def sum(args: Int*) = args.reduceLeft(_+_)
|
变量
1 2 3 4
| var x = 5 val x = 5 x=6 var x: Double = 5
|
包
1 2 3 4 5 6 7 8 9 10
| import scala.collection._ import scala.collection.Vector
import scala.collection.{Vector, Sequence}
import scala.collection.{Vector => Vec28}
import java.util.{Date => _, _}
package pkg { ... }
|
数据结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| (1,2,3)
var (x,y,z) = (1,2,3)
var x,y,z = (1,2,3)
var xs = List(1,2,3) xs(2) 1 :: List(2,3) 1 to 5 1 until 6
1 to 10 by 2
() (空括号)
|
控制结构
条件
1
| if (check) happy else sad
|
条件(语法糖)
1 2
| if (check) happy same as if (check) happy else ()
|
while 循环
1
| while (x < 5) { println(x); x += 1}
|
do while 循环
1
| do { println(x); x += 1} while (x < 5)
|
break. (slides)
1 2 3 4 5 6
| import scala.util.control.Breaks._ breakable { for (x <- xs) { if (Math.random < 0.1) break } }
|
for 表达式: filter/map
1 2 3
| for (x <- xs if x%2 == 0) yield x*10
xs.filter(_%2 == 0).map(_*10)
|
for 表达式: 解构绑定
1 2 3
| for ((x,y) <- xs zip ys) yield x*y
(xs zip ys) map { case (x,y) => x*y }
|
for 表达式: 叉乘
1 2 3
| for (x <- xs; y <- ys) yield x*y
xs flatMap {x => ys map {y => x*y}}
|
for 表达式: 不可避免的格式
1 2 3
| for (x <- xs; y <- ys) { println("%d/%d = %.1f".format(x, y, x/y.toFloat)) }
|
for 表达式: 包括上边界的遍历
1 2 3
| for (i <- 1 to 5) { println(i) }
|
for 表达式: 忽略上边界的遍历
1 2 3
| for (i <- 1 until 5) { println(i) }
|
模式匹配
在函数的参数中使用模式匹配
1 2 3 4
| (xs zip ys) map { case (x,y) => x*y }
(xs zip ys) map( (x,y) => x*y )
|
可以匹配任何Int类型值的名称
1 2 3 4 5
| val v42 = 42 Some(3) match { case Some(v42) => println("42") case _ => println("Not 42") }
|
❌ BAD: “v42” 被解释为可以匹配任何Int类型值的名称,打印输出”42”
1 2 3 4 5
| val v42 = 42 Some(3) match { case Some(`v42`) => println("42") case _ => println("Not 42") }
|
✅ GOOD: 有反引号的 “v42
” 被解释为已经存在的 val v42
,所以输出的是 “Not 42”.
1 2 3 4 5
| val UppercaseVal = 42 Some(3) match { case Some(UppercaseVal) => println("42") case _ => println("Not 42") }
|
✅ GOOD: UppercaseVal 被视作已经存在的 val,而不是一个新的模式变量,因为它是以大写字母开头的,所以 UppercaseVal
所包含的值(42)和检查的值(3)不匹配,输出”Not 42”
面向对象
构造器参数 - 私有
1 2 3
| class C(x: R) same as class C(private val x: R) var c = new C(4)
|
构造器参数 - 公有
1 2 3
| class C(val x: R) var c = new C(4) c.x
|
构造函数就是类的主体
1 2 3 4 5 6 7
| class C(var x: R) { assert(x > 0, "positive please") var y = x val readonly = 5 private var secret = 1 def this = this(42) }
|
匿名类
定义一个抽象类
1
| abstract class D { ... }
|
定义一个继承子类
1
| class C extends D { ... }
|
继承与构造器参数
1 2
| class D(var x: R) class C(x: R) extends D(x)
|
愿望清单: 默认自动传参
定义一个单例
1
| object O extends D { ... }
|
和模块一样
特质
1 2 3
| trait T { ... } class C extends T { ... } class C extends D with T { ... }
|
带有实现的接口,没有构造参数
多个特质
1 2 3
| trait T1; trait T2 class C extends T1 with T2 class C extends D with T1 with T2
|
必须声明覆盖该方法
1
| class C extends D { override def f = ...}
|
创建对象
1 2 3
| new java.io.File("f") new List[Int] List(1,2,3)
|
类字面量
类型检查 (运行时)
类型强制转换 (运行时)
归属 (编译时)