Skip to content

Instantly share code, notes, and snippets.

@tyrcho
Last active March 6, 2018 13:10
Show Gist options
  • Save tyrcho/89d3b000bcc1e52af31e to your computer and use it in GitHub Desktop.
Save tyrcho/89d3b000bcc1e52af31e to your computer and use it in GitHub Desktop.
Scala CheatSheet
//Values and definitions
val x = 5 // constant, evaluated once
def y = 5 // definition (function), evaluated at each call
lazy val z = 5 // constant with lazy evaluation
var v = 5 // variable, only use when really needed
//Control constructs
if (true) 1 else 2 // conditional _expression_, of type Int
if (true) 1 // /!\ this is the same as
if (true) 1 else () // which is of type AnyVal
//loop structures for imperative programming
var i = 0
while (i < 5) { println(i); i += 1}
do { println(i); i += 1} while (i < 5)
//Tuples
val t = (1, 2, 3)
val (x, y, z) = t //destructuring bind: tuple unpacking via pattern matching
val i = t._1 // access to tuple elements; index starts at 1; avoid if possible (readability)
//Case classes (gives more maintainable code)
case class Vector3d(x: Int, y: Int, z: Int)
val p = Vector3d(1, 2, 3)
val j = p.x
// Basic immutable lists
val xs = List(1, 2, 3)
val List(a, b, c) = List(1, 2, 3) // unpacking via pattern matching
xs(2) //paren indexing; sugar for xs.apply(2)
0 :: xs //cons : creates a new list with prepended element
// Ranges
1 to 5
1 until 6 // excludes the upper bound
1 to 10 by 2 // specify step
() //(empty parens) sole member of the Unit type (like C/Java void)
for (x <- 1 to 10 if x % 2 == 0) yield x * 10
// or (preferred for longer expressions)
for {
x <- 1 to 10
if x % 2 == 0
} yield x * 10
// sugar for
(1 to 10).filter(_ % 2 == 0).map(_ * 10)
for {
(x, y) <- (1 to 5) zip (6 to 10)
// pattern matching can be used here also
} yield x * y
// sugar for
((1 to 5) zip (6 to 10)).map {
case (x, y) => x * y
}
for (x <- 1 to 5; y <- 6 to 10) yield x * y
// for comprehension: cross product (all possible combinations of x and y)
1 to 5 flatMap { x => 6 to 10 map { y => x * y } }
for (x <- 1 to 5; y <- 6 to 10) {
// for comprehension: imperative style
println("%d/%d = %.1f".format(x, y, x * y))
}
def f(x: Int): Int = { x * x }
def f(x: Int): Int = x * x // optional {}
def f(x: Int) = x * x // inferred return type
// mandatory return type for
def gcd(a:Int, b:Int): Int = recursive function
if (b == 0) a else gcd(b, a % b)
def log(x: Any): Unit = println(x) // side effects only => Unit
def log(x: => Any): Unit = println(x) // call-by-name argument
(x: Int) => x * x // anonymous function
(1 to 5).map(x => x * x) // with inferred type for argument
(1 to 5).map(2 * _)
(1 to 5).reduceLeft(_ + _) // anonymous function: underscore is positionally matched argument
(1 to 5).map { x => val y=x*2; y } // anonymous function: block style; returns last expression
val zscore = (mean: Double, sd: Double) => (x: Double) => (x - mean) / sd
// currying, obvious syntax
def zscore(mean: Double, sd: Double) = (x: Double) => (x - mean) / sd
// currying, obvious syntax
def zscore(mean: Double, sd: Double)(x: Double) = (x - mean) / sd
// currying, sugar syntax. but then:
val normer = zscore(7, 0.4) _ // need trailing underscore to get the partial function, only for the sugar version
def mapmake[T](g: T = >T)(seq: List[T]) = seq.map(g) //generic type.
def sum(args: Int*) = args.reduceLeft(_ + _) // varargs
//wildcard import :
import collection._
//selective imports
import collection.immutable.Vector
import collection.immutable.{ Vector, List }
// renames import to avoid conflict with types alreading in the scope
import java.util.{ List => JList }
// import all from java.util except Date.
import java.util.{ Date => _, _ }
// syntax to define a package container for functions, types
package object mypkg {
type Predicate = Int => Boolean
def abs(x: Int) = if (x > 0) x else -x
}
class C(x: Int)
val c = new C(4) // instanciation
List(1, 2, 3) // factory method in companion object
val cl = classOf[String] //class literal (java String.class)
val isString = c.isInstanceOf[String] // type check (runtime)
val myString = c.asInstanceOf[String] // cast (runtime)
//same as
class D(private val x: Int)
val d = new D(4)
// (x is a constructor param and private member)
class E(val x: Int)
var e = new E(4)
e.x
// x is now also a public member
class F(var x: Int) { // x is now modifiable
assert(x > 0, "positive please") //class body == constructor
def y = x //declare a public member
val readonly = 5 // declare a gettable but not settable member
private var secret = 1 // declare a private member
def this() = this(42) // alternate constructor, calls primary constructor
}
val s = new { val x = 2 } //anonymous class
println(s.x)
abstract class Abstract(i: Int) { // non-instanciable
def prop: Int //abstract method}
}
class Concrete(i: Int) extends Abstract(i) { // inherited class with call to super constructor
def prop = i //implements the abstract method
}
object Singleton extends Concrete(5)
trait T { def m: String } // purely abstract, like an interface
trait U { val n = "toto" } // traits can have concrete implementation
class Mixin extends Concrete(5) with T with U { // multiple inheritance
val m = "hello" // a val or var can implement a def
override def toString = "my mixin"
}
List() match {
case x :: xs =>
// matches a list head & tail
// introduces x and xs to the scope
case _ =>
// matches anything
}
Option(1) match {
case Some(value) => value
// introduces value to the scope
case None => "default"
}
val value = 3
Option(1) match {
case Some(`value`) =>
// compares to an existing value, same as
case Some(v) if v == value =>
}
val UppercaseVal = 42
Some(3) match {
case Some(UppercaseVal) => "42"
// /!\ UppercaseVal is treated as an existing val, rather than a new pattern variable, because it starts with an uppercase letter.
//Thus, the value contained within UppercaseVal is checked against 3, and "Not 42" is returned.
case _ => "Not 42"
}
List(1, "") match {
case List(e1: String, e2: Int) =>
// checks the types of e1 and e2
case l @ List(a @ List(b, c), d) =>
//creates aliases for the matched elements
}
((1 to 5) zip (6 to 10)).map {
case (x, y) => x * y
// you need {} not () to use pattern matching to define an anonymous function
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment