Skip to content

Instantly share code, notes, and snippets.

@mmiliaus
Last active January 1, 2016 06:19
Show Gist options
  • Save mmiliaus/8103782 to your computer and use it in GitHub Desktop.
Save mmiliaus/8103782 to your computer and use it in GitHub Desktop.
Functional Programming Principles in Scala
// Vectors
val nums = Vector(1, 2, 3, -88)
x +: xs // Create a new vector with leading element x, followed by all elements of xs.
xs :+ x // Create a new vector with trailing element x, preceded by all elements of xs.
// Ranges
val r: Range = 1 until 5
val s: Range = 1 to 5
1 to 10 by 3
6 to 1 by -2
// flatMap
val l = List(1,2,3,4,5)
def f(x: Int) = if (v > 2) Some(v) else None
def g(v:Int) = List(v-1, v, v+1)
l.map(x => g(x))
// res64: List[List[Int]] = List(List(0, 1, 2), List(1, 2, 3), List(2, 3, 4), List(3, 4, 5), List(4, 5, 6))
l.flatMap(x => g(x))
// res65: List[Int] = List(0, 1, 2, 1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 5, 6)
l.map(x => f(x))
// res66: List[Option[Int]] = List(None, None, Some(3), Some(4), Some(5))
l.flatMap(x => f(x))
// res67: List[Int] = List(3, 4, 5)
// for-expression
for {
i <- 1 until n
j <- 1 until i
if isPrime(i + j)
} yield (i, j)
// To find the names of all authors who have written at least two books present in the database.
for {
b1 <- books
b2 <- books
if b1.title < b2.title
a1 <- b1.authors
a2 <- b2.authors
if a1 == a2
} yield a1
// Maps
val capitalOfCountry = Map("US" -> "Washington", "Switzerland" -> "Bern")
// Maps support the same collection operations as other iterables do.
val countryOfCapital = capitalOfCountry map {
case(x, y) => (y, x)
} // Map("Washington" -> "US", "Bern" -> "Switzerland")
// Maps are "partial functions"
capitalOfCountry("US") // Washington
// Sorted and GroupBy
val fruit = List("apple", "pear", "orange", "pineapple")
fruit sortWith (_.length < _.length) // List("pear", "apple", "orange", "pineapple")
fruit.sorted // List("apple", "orange", "pear", "pineapple")
fruit groupBy (_.head) //> Map(p -> List(pear, pineapple),
//| a -> List(apple),
//| o -> List(orange))
// Mapping a Map
val m = Map("a" -> 1, "b" -> 2) //> m : scala.collection.immutable.Map[String,Int] = Map(a -> 1, b -> 2)
val incM = m map {case (key, value) => (key, value + 1)}
//> incM : scala.collection.immutable.Map[String,Int] = Map(a -> 2, b -> 3)
// Setting default key value
val cap1 = capitalOfCountry withDefaultValue "<unknown>"
cap1("Andorra") // <unknown>
// Repeated parameter
def Polynom(bindings: (Int, Double)*) = new Polynom(bindings.toMap withDefaultValue 0)
Polynom(1 -> 2.0, 3 -> 4.0, 5 -> 6.2)
// :: -- prepend
1 :: 2 :: List() //> res3: List[Int] = List(1, 2)
// pattern matching
List(1,2,3) match {
case x :: xs => {
println(x) //> 1
println(xs) //| List(2, 3)
}
}
// sublists and element access:
xs.length
xs.last
xs.init
xs.take n
xs.drop n
xs(n) // n-th element of the xs list
// creating new lists
xs ++ ys
xs.reverse
xs.updated(n, x) // new list, with n-th element updated with x
// finding elements
xs.indexOf x
xs.contains x
// msort using pairs
def msort(xs: List[Int]): List[Int] = {
val n = xs.length / 2
if (n == 0) xs
else {
def merge(xs: List[Int], ys: List[Int]): List[Int] =
(xs, ys) match {
case (Nil, b) => b
case (a, Nil) => a
case (x :: xs1, y :: ys1) =>
if (x < y) x :: merge(xs1, ys)
else y :: merge(xs, ys1)
}
val (fst, snd) = xs splitAt n
merge(msort(fst), msort(snd))
}
}
// higher order list functions
xs.map f
xs.filter f
xs.filterNot f
xs.partition f // same as [filter(f), filterNot(f)]
xs.takeWhile f // the longest prefix of list xs consisting of elements that satisfy f
xs.dropWhile f // the remainder of the list xs, after droping the longest prefix that satisfies f
xs.span // [takeWhile(f), dropWhile(f)]
// Reduction of lists
xs.foldLeft(0)(_ + _)
+
/ \
/ xN
...
+
/ \
+ x2
/ \
0 x1
xs.foldRight(List())(_ :: _)
::
/ \
x1 ::
/ \
x2 ...
/ \
xN List()
// # Apply
object L {
def apply[T](): List[T] = List()
def apply[T](x: T): List[T] = List(x)
def apply[T](x: T, y: T): List[T] = List(x, y)
}
L() //> res0: List[Nothing] = List()
L(1) //> res1: List[Int] = List(1)
L(1,2) //> res2: List[Int] = List(1, 2)
// # Case class
case class Number(n: Int)
// Scala implicitly defines companion object `Number` with `apply` method
//
// object Number {
// def apply(n: Int) = new Number(n)
// }
// thus
Number(1) //> res1: Week4.FuncDecomp.Number = Number(1)
Number(11) //> res2: Week4.FuncDecomp.Number = Number(11)
// # Pattern Matching
trait Expr {
def eval: Int = this match {
case Number(n) => n
case Sum(e1, e2) => e1.eval + e2.eval
case Prod(Sum(e1, e2), Sum(e3, e4)) => Sum(e1, e2).eval * Sum(e3, e4).eval
case Prod(Sum(e1, e2), e3) => Sum(e1, e2).eval * e3.eval
case Prod(e1, Sum(e2, e3)) => e1.eval * Sum(e2, e3).eval
case Prod(e1, e2) => e1.eval * e2.eval
}
}
case class Number(n:Int) extends Expr
case class Sum(e1: Expr, e2: Expr) extends Expr
case class Prod(x: Expr, y:Expr) extends Expr
Prod(Sum(Number(1), Number(2)), Number(2)).eval
//> res0: Int = 6
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment