L09. Scala collections

val letters = Vector("v", "m", "n", "i")
 
/* the colon operator, allways indicates "associativity"
*   collection :@ element
*
*   element #: collection
*
*  */
letters :+ "z"
"a" +: letters
 
 
/* Ranges
*  (Int, Int) => Range
*  _.to(_)
*
*  (Int, Int) => Range
*  _.until(_)
*
*  (Range, Int) => Range
*  _.by(_)
*
*
* */
1.to(5)
1 to 5
 
1.until(5)
 
1 until 5
 
1 to 5 by 2
 
/* shorthand
a b c
for:
a.b(c)
 */
 
/*
 In Scala you can define functions that are not named only with
 alphabetic characters
 
*/
 
trait Nat {
  def +(n: Nat): Nat
  def -(n: Nat): Nat  // difference over naturals, not integers
}
 
case object Zero extends Nat {
  override def + (n: Nat): Nat = n
  override def - (n: Nat): Nat = Zero
}
 
case class Succ(n: Nat) extends Nat {
  override def + (m: Nat): Nat = Succ(n + m)
  override def - (m: Nat): Nat =
    m match {
      case Zero => Succ(n)
      case Succ(mp) => n - mp
    }
}
 
/* Maps */
val gradebook: Map[String,Int] =
  Map("John" -> 5 , "Anne" -> 9 , "Mike" -> 4)
 
"John".->(5) // will return a pair ("John", 5)
 
//indexing a map:
gradebook("John") // will return 5
 
//what happens when a key is not present?
//gradebook("Matei")
/* how to deal with inexistent keys ? */
 
// Option 1:
if (gradebook contains "Matei") gradebook("Matei")
else ""
 
// Option 2:
val g2 = gradebook.withDefaultValue(0) // a new gradebook that returns 0 for non-existent keys
// THIS MAKES GRADEBOOK A TOTAL FUNCTION
 
g2 + ("Matei" -> 0) // updates the current map with a new key/value entry. If the key exists, it will be updated. The function returns a new map
 
g2 ++ Map("A" -> 0, "B" -> 1) // merges two maps
 
g2("Matei")
 
// Option 3:
// using the get function:
gradebook.get("Matei")
 
/* _.get(_)
*
*  (Map[K,V],K) => Option[V]
*  */
/*
trait Option[A] {}
case class None[A]() extends Option[A] {}
case class Some[A](value: A) extends Option[A] {}
*/
 
def head (l: List[Int]): Option[Int] =
  l match {
    case Nil => None
    case x :: _ => Some(x)
  }
 
val list = List(1)
 
head(list) match {
  case None => "Error, empty list"
  case Some(x) => "The first element is:"+x.toString
}