Cheatsheet¶
About¶
Thanks to Brendan O’Connor, this cheatsheet aims to be a quick reference of Scala syntactic constructions. Licensed by Brendan O’Connor under a CC-BY-SA 3.0 license.
Variables¶
- variable
var x = 5- constant
- GOOD
val x = 5BADx = 6 - explicit type
var x: Double = 5
Functions¶
- define function
- GOOD
def f(x: Int) = { x*x }BADdef f(x: Int) { x*x }[1] - define function
- GOOD
def f(x: Any) = println(x)BADdef f(x) = println(x)[2] - type alias
type R = Double- call-by-value
def f(x: R)- call-by-name
def f(x: => R)- anonymous function
(x:R) => x*x- anonymous function: underscore is positionally matched arg
(1 to 5).map(_*2)(1 to 5).reduceLeft( _+_ )- anonymous function: to use an arg twice, have to name it
(1 to 5).map( x => x*x )- anonymous function: bound infix method.
- GOOD
(1 to 5).map(2*)BAD(1 to 5).map(*2)[3] - anonymous function: block style returns last expression
(1 to 5).map { val x=_*2; println(x); x }- anonymous functions: pipeline style. (or parens too)
(1 to 5) filter {_%2 == 0} map {_*2}- anonymous functions: to pass in multiple blocks, need outer parens
def compose(g:R=>R, h:R=>R) = (x:R) => g(h(x))val f = compose({_*2}, {_-1})- currying, obvious syntax
val zscore = (mean:R, sd:R) => (x:R) => (x-mean)/sd- currying, obvious syntax
val zscore = (mean:R, sd:R) => (x:R) => (x-mean)/sd- currying, sugar syntax
def zscore(mean:R, sd:R)(x:R) = (x-mean)/sdval normer = zscore(7, 0.4)_need trailing underscore to get the partial, only for the sugar version- generic type
def mapmake[T](g:T=>T)(seq: List[T]) = seq.map(g)- infix sugar
5.+(3); 5 + 3(1 to 5) map (_*2)- varargs
def sum(args: Int*) = args.reduceLeft(_+_)
Packages¶
- wildcard import
import scala.collection._- selective import
import scala.collection.Vectorimport scala.collection.{Vector, Sequence}- renaming import
import scala.collection.{Vector => Vec28}- import all from
java.utilexceptDate import java.util.{Date => _, _}- declare a package
package pkgat start of filepackage pkg { ... }
Data Structures¶
- tuple literal
(1,2,3)- destructing bind: tuple unpacking via pattern matching
- GOOD
var (x,y,z) = (1,2,3)BADvar x,y,z = (1,2,3)[4] - list (immutable)
var xs = List(1,2,3)- paren indexing (slides)
xs(2)- cons
1 :: List(2,3)- range sugar
1 to 5same as1 until 61 to 10 by 2- sole member of the unit type (like C/Java void)
()(empty parens)
Control Constructs¶
- conditional
if (check) happy else sad- conditional sugar
if (check) happysame asif (check) happy else ()- while loop
while (x < 5) { println(x); x += 1}- do while loop
do { println(x); x += 1} while (x < 5)- break (slides)
import scala.util.control.Breaks._ breakable { for (x <- xs) { if (Math.random < 0.1) break } }
- for comprehension: filter/map
for (x <- xs if x%2 == 0) yield x*10same asxs.filter(_%2 == 0).map(_*10)- for comprehension: destructing bind
for ((x,y) <- xs zip ys) yield x*ysame as(xs zip ys) map { case (x,y) => x*y }- for comprehension: cross product
for (x <- xs; y <- ys) yield x*ysame asxs flatMap {x => ys map {y => x*y}}- for comprehension: imperative-ish sprintf-style
for (x <- xs; y <- ys) { println("%d/%d = %.1f".format(x,y, x*y)) }
- for comprehension: iterate including the upper bound
for (i <- 1 to 5) { println(i) }
- for comprehension: iterate omitting the upper bound
for (i <- 1 until 5) { println(i) }
Pattern Matching¶
- use case in function args for pattern matching
- GOOD
(xs zip ys) map { case (x,y) => x*y }BAD(xs zip ys) map( (x,y) => x*y ) v42is interpreted as a name matching any Int value, and “42” is printedBAD
val v42 = 42 Some(3) match { case Some(v42) => println("42") case _ => println("Not 42") }
`v42`with backticks is interpreted as the existing valv42, and “Not 42” is printedGOOD
val v42 = 42 Some(3) match { case Some(`v42`) => println("42") case _ => println("Not 42") }
UppercaseValis treated as an existing val, rather than a new pattern variable, because it starts with an uppercase letter. Thus, the value contained withinUppercaseValis checked against3, and “Not 42” is printed.GOOD
val UppercaseVal = 42 Some(3) match { case Some(UppercaseVal) => println("42") case _ => println("Not 42") }
Object Orientation¶
- constructor params - private
class C(x: R)same asclass C(private val x: R)var c = new C(4)- constructor params - public
class C(val x: R)var c = new C(4)c.x- constructor is class body, declare a public member, declare a gettable but not settable member, declare a private member, alternative constructor
class C(var x: R) { assert(x > 0, "positive please") var y = x val readonly = 5 private var secret = 1 def this = this(42) }
- anonymous class
new{ ... }- define an abstract class. (non-createable)
abstract class D { ... }- define an inherited class
class C extends D { ... }- inheritance and constructor params. (wishlist: automatically pass-up params by default)
class D(var x: R)class C(x: R) extends D(x)- define a singleton. (module-like)
object O extends D { ... }- traits [5]
trait T { ... }class C extends T { ... }class C extends D with T { ... }- multiple traits
trait T1; trait T2class C extends T1 with T2class C extends D with T1 with T2- must declare method overrides
class C extends D { override def f = ...}- create object
new java.io.File("f")- callable factory shadowing the type
- GOOD
List(1,2,3)BADnew List[Int][6] - class literal
classOf[String]- type check (runtime)
x.isInstanceOf[String]- type cast (runtime)
x.asInstanceOf[String]- ascription (compile time)
x: String
Footnotes
| [1] | Hidden error: without = it’s a unit-returning procedure; causes havoc |
| [2] | Syntax error: need types for every arg |
| [3] | Use 2* for sanity’s sake instead |
| [4] | Hidden error: each assigned to the entire tuple |
| [5] | Interfaces-with-implementation. no constructor params. mixin-able |
| [6] | Type error: abstract type |