Last active
January 1, 2016 06:19
-
-
Save mmiliaus/8103782 to your computer and use it in GitHub Desktop.
Functional Programming Principles in Scala
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// :: -- 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() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// # 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