Scala Cheatsheet
Scala Cheatsheet
Language
Contributed by Brendan O’Connor
感谢 Brendan O’Connor,本速查表可以用于快速地查找Scala语法结构。Licensed by Brendan O’Connor under a CC-BY-SA 3.0 license.
变量 | |
var x = 5 |
可变变量 |
Good val x = 5 Bad x=6 |
常量 |
var x: Double = 5 |
显式类型 |
函数 | |
Good def f(x: Int) = { x*x } Bad def f(x: Int) { x*x } |
定义函数 潜在风险: 不加“=”号将会是一段返回Unit类型的过程,这将会导致意想不到的错误。 |
Good def f(x: Any) = println(x) Bad 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 ) |
匿名函数: 必须命名以后才可以多次使用同一个参数。 |
Good (1 to 5).map(2*) Bad (1 to 5).map(*2) |
匿名函数: 绑定中缀方法,明智的做法是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(_+_) |
变长参数 |
包 | |
import scala.collection._ |
通配符导入 |
import scala.collection.Vector import scala.collection.{Vector, Sequence} |
选择性导入 |
import scala.collection.{Vector => Vec28} |
重命名导入 |
import java.util.{Date => _, _} |
导入java.util包里除Date之外的一切。 |
package pkg at start of file package pkg { ... } |
声明这是一个包 |
数据结构 | |
(1,2,3) |
元组字面量 (Tuple3 ) |
var (x,y,z) = (1,2,3) |
解构绑定:通过模式匹配来解构元组。 |
Badvar x,y,z = (1,2,3) |
潜在风险:整个元组被赋值给了每一个变量。 |
var xs = List(1,2,3) |
列表 (不可变)。 |
xs(2) |
用括号索引 (slides) |
1 :: List(2,3) |
Cons(构成) |
1 to 5 等价于 1 until 6 1 to 10 by 2 |
Range类型(语法糖) |
() (空括号) |
Unit类型的唯一成员 (相当于 C/Java 里的void). |
控制结构 | |
if (check) happy else sad |
条件 |
if (check) happy same as if (check) happy else () |
条件(语法糖) |
while (x < 5) { println(x); x += 1} |
while循环 |
do { println(x); x += 1} while (x < 5) |
do while循环 |
import scala.util.control.Breaks._ breakable { for (x <- xs) { if (Math.random < 0.1) break } } |
break. (slides) |
for (x <- xs if x%2 == 0) yield x*10 等价于 xs.filter(_%2 == 0).map(_*10) |
for 表达式: filter/map |
for ((x,y) <- xs zip ys) yield x*y 等价于 (xs zip ys) map { case (x,y) => x*y } |
for 表达式: 解构绑定 |
for (x <- xs; y <- ys) yield x*y 等价于 xs flatMap {x => ys map {y => x*y}} |
for 表达式: 叉乘 |
for (x <- xs; y <- ys) { println("%d/%d = %.1f".format(x, y, x/y.toFloat)) } |
for 表达式: 不可避免的格式 sprintf-style |
for (i <- 1 to 5) { println(i) } |
for 表达式: 包括上边界的遍历 |
for (i <- 1 until 5) { println(i) } |
for 表达式: 忽略上边界的遍历 |
模式匹配 | |
Good (xs zip ys) map { case (x,y) => x*y } Bad (xs zip ys) map( (x,y) => x*y ) |
在函数的参数中使用模式匹配的例子。 |
Badval v42 = 42 Some(3) match { case Some(v42) => println("42") case _ => println("Not 42") } |
“v42” 被解释为可以匹配任何Int类型值的名称,打印输出”42”。 |
Goodval v42 = 42 Some(3) match { case Some(`v42`) => println("42") case _ => println("Not 42") } |
有反引号的 “`v42`” 被解释为已经存在的val v42 ,所以输出的是 “Not 42”. |
Goodval UppercaseVal = 42 Some(3) match { case Some(UppercaseVal) => println("42") case _ => println("Not 42") } |
UppercaseVal 被视作已经存在的 val,而不是一个新的模式变量,因为它是以大写字母开头的,所以UppercaseVal 所包含的值(42)和检查的值(3)不匹配,输出”Not 42”。 |
面向对象 | |
class C(x: R) same as class C(private val x: R) var c = new C(4) |
构造器参数 - 私有 |
class C(val x: R) var c = new C(4) c.x |
构造器参数 - 公有 |
class C(var x: R) { assert(x > 0, "positive please") var y = x val readonly = 5 private var secret = 1 def this = this(42) } |
构造函数就是类的主体 声明一个公有成员变量 声明一个可get但不可set的成员变量 声明一个私有变量 可选构造器 |
new{ ... } |
匿名类 |
abstract class D { ... } |
定义一个抽象类。(不可创建) |
class C extends D { ... } |
定义一个继承子类。 |
class D(var x: R) class C(x: R) extends D(x) |
继承与构造器参数(愿望清单: 默认自动传参) |
object O extends D { ... } |
定义一个单例(和模块一样) |
trait T { ... } class C extends T { ... } class C extends D with T { ... } |
特质 带有实现的接口,没有构造参数。 mixin-able. |
trait T1; trait T2 class C extends T1 with T2 class C extends D with T1 with T2 |
(混入)多个特质 |
class C extends D { override def f = ...} |
必须声明覆盖该方法。 |
new java.io.File("f") |
创建对象。 |
Bad new List[Int] Good List(1,2,3) |
类型错误: 抽象类型 相反,习惯上:调用工厂(方法)会自动推测类型 |
classOf[String] |
类字面量 |
x.isInstanceOf[String] |
类型检查 (运行时) |
x.asInstanceOf[String] |
类型强制转换 (运行时) |
x: String |
归属 (编译时) |