Friday, September 28, 2012

Structural Typing Zur Hilfe

    class CreditRiskIndicators (val ead: Double) {}
    
    abstract class FinancialInstrument {  def getCreditRiskIndicators() : CreditRiskIndicators  }
    abstract class Account {  def getCreditRiskIndicators() : CreditRiskIndicators  }
    abstract class Position {  def getCreditRiskIndicators() : CreditRiskIndicators  }

Structural Food Typing

  abstract class Dickmacher {}
  case class Beverage (name: String, cal: Int) extends Dickmacher
  case class Food (name: String, cal: Int) extends Dickmacher
  case class Meal (name: String, food: Food, drink: Beverage) extends Dickmacher
  case class Combo (starter: Dickmacher, main: Dickmacher) extends Dickmacher

  //hat wie Food einen val 'cal', erbt aber nicht von Dickmacher
  class Elephant(val cal: Int) {
    override def toString() : String = "Elephant"
  }

  
  class Person(name: String) {
      def eat(food: Food) = {
          println("Ich habe " + food + " mit " + food.cal + " cal gegessen.")
      }
  }
  
  val person = new Person("Horst") 
  person.eat(Food("Diatschokolade", 5))
//  person.eat(new Elephant(500000)) compile error
  

  
  class Allesfresser(name: String) {
      def eat(food: { def cal : Int}) = {
          println("Ich habe " + food + " mit " + food.cal + " cal gegessen.")
     }
  }
  
  val allesFresser = new Allesfresser("Anna")
  allesFresser.eat(Food("Schnitzel", 400))
  allesFresser.eat(new Elephant(500000))

Pattern Matching Unpack

  abstract class Dickmacher
  case class Beverage (name: String, cal: Int) extends Dickmacher
  case class Food (name: String, cal: Int) extends Dickmacher
  case class Meal (name: String, food: Food, drink: Beverage) extends Dickmacher
  case class Combo (starter: Dickmacher, main: Dickmacher) extends Dickmacher

  def unpack(food: Dickmacher) : List[Dickmacher] = food match {
    case a: Beverage => a :: Nil
    case b: Food => b :: Nil
    case Meal(_, b , a) => a :: b :: Nil
    case Combo(a, b) => unpack(a) ::: unpack(b)
    case _ => Nil
  }
  
  val coke = Beverage("Cola Light", 50)
  val burger = Food("Big Mac", 400)
  
  
  val cokeLight = Beverage("Cola", 100)
  val wannaBeBurger = Food("Veggie Mac", 50)
  

  val cokeCombo = Combo(coke, cokeLight)
  println(unpack(cokeCombo))
  
  
  val burgerCombo = Combo(burger, wannaBeBurger)
  println(unpack(burgerCombo))
  
  
  val monsterCombo = Combo(Combo(burgerCombo, cokeCombo), Food("Nachspeise", 600));
  println(unpack(monsterCombo))

Pattern Matching Simplify

  abstract class Dickmacher
  case class Beverage (name: String, cal: Int) extends Dickmacher
  case class Food (name: String, cal: Int) extends Dickmacher
  case class Meal (name: String, food: Food, drink: Beverage) extends Dickmacher
  case class Combo (starter: Dickmacher, main: Dickmacher) extends Dickmacher

  def simplify(d: Dickmacher) : Dickmacher = {
    d match {
      case Combo(Food(x,cal1), Food(y,cal2)) => simplify(Food(x + " mit " + y, cal1 + cal2))
      case Combo(Beverage(x,cal1), Beverage(y,cal2)) => simplify(Beverage(x + " mit " + y, cal1 + cal2))
      case Combo(a, b) => Combo(simplify(a), simplify(b))
      case _ => d 
    }
  }
  
  val coke = Beverage("Cola Light", 50)
  val burger = Food("Big Mac", 400)
  
  
  val cokeLight = Beverage("Cola", 100)
  val wannaBeBurger = Food("Veggie Mac", 50)
  

  val cokeCombo = Combo(coke, cokeLight)
  println(simplify(cokeCombo))
  
  
  val burgerCombo = Combo(burger, wannaBeBurger)
  println(simplify(burgerCombo))
  
  
  
  val monsterCombo = Combo(burgerCombo, cokeCombo);
  println(simplify(monsterCombo))

Pattern Matching Case Classes

  abstract class Dickmacher
  case class Beverage (name: String, cal: Int) extends Dickmacher
  case class Food (name: String, cal: Int) extends Dickmacher
  case class Meal (name: String, food: Food, drink: Beverage) extends Dickmacher
  case class Combo (starter: Dickmacher, main: Dickmacher) extends Dickmacher

  
  def drink(bev: Beverage) : Unit = {
      bev match {
          case Beverage("Kaffee", 30) => println("Zucker und Milch fehlen")
          case Beverage(_, c) if c < 50 => println("Mehr Kalorien")
          case Beverage(n, c) if c < 100 => println(n + " hat zu wenig Kalorien: " + c)
          case Beverage("Cola", 400) => println("Ahhh")
          case _ => println("Bäh!")
      }
  }
  
  def eat(bev: Meal) : Unit = {
      bev match {
          case Meal(_, Food(_, a), Beverage("Coke", b)) if a >= 400 && b >= 100 => println("Haben wollen!")
          case _ => println("Bäh!")
      }
  }
  
  println(drink(Beverage("Kaffee", 30)))
  println(drink(Beverage("Tee", 10)))
  println(drink(Beverage("Cola Light", 50)))
  println(drink(Beverage("Cola", 40)))
  println(drink(Beverage("Saft", 500)))
  
  eat(Meal("Uschi's Fried Chicken", Food("Chicken", 600), Beverage("Coke Zero", 0)))
  eat(Meal("Uschi's Fried Chicken+", Food("Chicken", 600), Beverage("Coke", 100)))

Pattern Matching Cal

  abstract class Dickmacher
  case class Beverage (name: String, cal: Int) extends Dickmacher
  case class Food (name: String, cal: Int) extends Dickmacher
  case class Meal (name: String, food: Food, drink: Beverage) extends Dickmacher
  case class Combo (starter: Dickmacher, main: Dickmacher) extends Dickmacher

  def totalCal(food: Dickmacher) : Int = food match {
    case Beverage(_, x) => x
    case Food(_, x) => x
    case Meal(_, x, y) => x.cal + y.cal
    case Combo(a: Food, b) => a.cal + totalCal(b)
    case Combo(a: Beverage, b) => a.cal + totalCal(b)
    case Combo(a: Meal, b) => totalCal(a) + totalCal(b)
    case Combo(a: Combo, b) => totalCal(a) + totalCal(b)
    case _ => throw new AssertionError();
  }
  
  val coke = Beverage("Cola Light", 50)
  val burger = Food("Big Mac", 400)
  
  val cokeLight = Beverage("Cola", 100)
  val wannaBeBurger = Food("Veggie Mac", 50)
  

  val cokeCombo = Combo(coke, cokeLight)
  println(totalCal(cokeCombo))
  
  
  val burgerCombo = Combo(burger, wannaBeBurger)
  println(totalCal(burgerCombo))
  
  
  val monsterCombo = Combo(Combo(burgerCombo, cokeCombo), Food("Nachspeise", 600));
  println(totalCal(monsterCombo))

Pattern Matching Beverages

  abstract class Dickmacher
  case class Beverage (name: String, cal: Int) extends Dickmacher
  case class Food (name: String, cal: Int) extends Dickmacher
  case class Meal (name: String, food: Food, drink: Beverage) extends Dickmacher
  case class Combo (starter: Dickmacher, main: Dickmacher) extends Dickmacher

  def countBeverages(food: Dickmacher) : Int = food match {
    case Beverage(_, x) => 1
    case Food(_, x) => 0
    case Meal(_, x, y) => 0
    case Combo(a: Food, b) => 0 + countBeverages(b)
    case Combo(a: Beverage, b) => 1 + countBeverages(b)
    case Combo(a: Meal, b) => 0 + countBeverages(b)
    case Combo(a: Combo, b) => 0 + countBeverages(b)
    case _ => throw new AssertionError();
  }
  
  val coke = Beverage("Cola Light", 50)
  val burger = Food("Big Mac", 400)
  
  
  val cokeLight = Beverage("Cola", 100)
  val wannaBeBurger = Food("Veggie Mac", 50)
  

  val cokeCombo = Combo(coke, cokeLight)
  println(countBeverages(cokeCombo))
  
  
  val burgerCombo = Combo(burger, wannaBeBurger)
  println(countBeverages(burgerCombo))
  
  
  val monsterCombo = Combo(Combo(burgerCombo, cokeCombo), Food("Nachspeise", 600));
  println(countBeverages(monsterCombo))

Pattern Matching Basics

  def matchAny(any: Any) = 
    any match {
          case "Huhu" => println("Hi")
          case 5  => println("high five");
          case a: Int  => println("Ich kann bis " + a + " zaehlen")
          case a: String  => println("Ein String")
          case (a,b) => println("Tuple mit Werten " + a + "und" + b )
          case Nil => println("Eine leere Liste")
          case List(1,2,3) => println("Liste mit den Werten 1,2,3")
          case List(a,_*) => println("Liste Laenge > 2 und  den Werten + " + a + ",*,...")
          case _ => println("Niemand passt zu: " + any)
      }
  
  
  println(matchAny("Huhu"))
  println(matchAny("5"))
  println(matchAny(10))

  class Person(name: String, weight: Int) { }
  val horst = (new Person("Horst", 55)) //compiler ignoriert fachliche Fehler
  
  println(matchAny(horst))
  println(List(horst, new Person("Anna", 105)))
  
  val desires = (horst, "Spank me!")
  println(matchAny(desires))
  
  println(matchAny(List(1,2)))
  println(matchAny(List(1,2,3)))
  println(matchAny(List(1,2,3,4,5)))

Duck Typing

  class Duck {
    def quack = println("Quack - I'm a duck")
  }
  
  class Hunter {
    def quack = println("Kwak, I'm a bad ass hunter")
  }

  def makeSomeNoise(duck: { def quack }) = {
    duck.quack
  }
  
  
  val duck = new Duck
  val hunter = new Hunter
  
  println(makeSomeNoise(duck))
  println(makeSomeNoise(hunter))

Case Classes

  abstract class Dickmacher
  case class Beverage(name: String, cal: Int) extends Dickmacher
  case class Food(name: String, cal: Int) extends Dickmacher
  case class Meal(name: String, food: Food, drink: Beverage) extends Dickmacher
  case class Combo(starter: Dickmacher, main: Dickmacher) extends Dickmacher

  val coke = Beverage("Cola", 50)
  val burger = Food("Big Mac", 400)

  println(coke + " and " + burger)

  val wormup = Meal("Happy Meal", burger, coke)
  val primetime = Combo(wormup, new Combo(Food("Muffin", 200), Beverage("Coffee", 30)))
  //deep toString
  println(wormup)
  println(primetime)

  //deep equals
  println(wormup.drink == Beverage("Cola", 50)) //true
  println(wormup.drink == primetime.main) //false
  
  val fatCombo = new Combo(Food("Muffin", 200), Beverage("Coffee", 30))
  val ohneZuckerCombo = new Combo(Food("Muffin", 200), Beverage("Coffee", 5))
  
  println(fatCombo == ohneZuckerCombo) //false
  println(ohneZuckerCombo == new Combo(Food("Muffin", 200), Beverage("Coffee", 5))) //true

Thursday, September 27, 2012

Closures

def someFunc() = {
  var someLocalVariable = 0;
  val closure1 = {()=> someLocalVariable += 5; someLocalVariable; };
  val closure2 = {()=> someLocalVariable -= 2; someLocalVariable; };
  (closure1, closure2);
}

val closures = someFunc();

println(closures._1());
println(closures._1());
println(closures._2());

Schedule

Basics
Case Classes and Pattern Matching
Functions - First class und anonym
Static Duck Typing or Structural Typing

Meassure Execution Time

  def meassureExecutionTime(block: => Unit) = {
    val start = System.currentTimeMillis();
    block
    val end = System.currentTimeMillis();
    end - start;
  }

  var sum = 0;
  val time = meassureExecutionTime {
    for (i <- 1 to 100000) {
      sum += i;
    }
  }
  println(sum);

  println(time);

Wednesday, September 26, 2012

Filter and Map

  case class Person(name : String, age : Int)

  val team = List(Person("Moni", 29), Person("Anna", 30), Person("Hannes", 40));

  println(team.filter((p : Person) => p.age > 35));
  println(team.filter(_.age > 35)); //shortcut
  
  println(team.map((p : Person) => p.name));
  println(team.map(_.name)); //shortcut
  
  val wise = (p : Person) => p.age > 35;
  println(team.filter(wise));

Brainteaser

 def twice[A](func: A=>A)= (a:A) => func(func(a));
 def chain[A](f1: A=>A, f2: A=>A)= (a:A) => f1(f2(a));

 val appendMark = (a:String) => a + "!";
 val prependMark = (a:String) => "!" + a;
 
 println( twice(chain(appendMark,prependMark))("Hello"));

Twice

 def twice1(func: Int=>Int)= (i:Int) => func(func(i));

 val add2 = (a:Int) => a + 2;
 val add4 = twice1(add2);
 
 println( add4(5));
 
 
 def twice2[T](func: T=>T)= (t:T) => func(func(t));
 
 val appendMark = (a:String) => a + "!";
 
 println( twice2(appendMark)("Hello"));

Group By Task

  abstract class Direction;
  case class Sell() extends Direction;
  case class Buy() extends Direction;
  case class Trade(direction : Direction, amount : Int, security : String);

  val trades = List(
      Trade(Buy(), 100, "AAPL"),
      Trade(Buy(), 200, "MSFT"),
      Trade(Buy(), 150, "INTC"),
      Trade(Buy(), 100, "AAPL"),
      Trade(Sell(), 100, "MSFT"),
      Trade(Sell(), 50, "INTC"),
      Trade(Buy(), 100, "AAPL")
      );

Monday, September 24, 2012

Call with Retry

  val random = new Random();
  def serviceWithBadConnection(): String = {
    if (random.nextFloat() < 0.8) throw new RuntimeException;
    "Data"
  }

  def call[T](retries: Int)(block: => T): Option[T] = {
    if (retries == 0) None 
    else {
      try {
        Some(block);
      } catch {
        case _ => {
          println("Retrying!");
          call(retries - 1)(block);
        }
      }
    }
  }
  
  val result = call(retries = 10) {
    val data = serviceWithBadConnection();
    "Enhanced " + data;
  }
  println(result);

Syntactic Sugar

  class Person {
    def isst(essen : String) = 
      println("Hmm " + essen);
    
    def +(person : Person) = "Frust";
  };
  
  val thomas = new Person;
  thomas.isst("Zucker");
  thomas isst "Zucker"
  
  val horst = new Person;
  val monika = new Person;
  println(horst + monika);

Functions, Params and Return

  def max1(a: Int, b: Int): Int = {
    if (a.>(b))
      a;
    else
      b;
  }

  def max2(a: Int, b: Int) =
    if (a > b) a else b;

  println(max1(1, 2));
  println(max2(1, 2));

Sunday, September 23, 2012

GroupBy, ForEach and Case

  case class Person(name : String, site : String)

  val team = List(
      Person("Moni", "M"), Person("Anna", "M"), 
      Person("Hannes", "N"), Person("Horst", "N"));
  
  val sites = team.groupBy(_.site);
  
  sites.foreach {
    case (site, persons) => 
      println(site + ": " + persons.map(_.name).mkString(", "));
  }

  sites.foreach {
    siteAndPersons =>
      println(siteAndPersons._1 + ": " + siteAndPersons._2.map(_.name).mkString(", "));
  }

Reduce, Min, MinBy, Sum and MkString

  case class Person(name : String, age : Int)

  val team = List(Person("Moni", 29), Person("Anna", 30), Person("Hannes", 40));
  val ages = team.map(_.age);
  val names = team.map(_.name);
  
  println(ages.reduce(Math.min(_,_)));
  println(ages.min);
  println(team.minBy(_.age));
  
  println(ages.reduce(_+_) / ages.size);
  println(ages.sum / ages.size);
  
  println(names.reduce(_+", "+_));
  println(names.mkString(", "));

Type Inference and Generics

  val string1 : String = "bla";
  val string2 = "bla";

  val strings1 : List[String] = List[String]("bla", "blub");
  val strings2 = List("bla", "blub");
  
  val numbers1 : List[Int] = List[Int](1,2,3);
  val numbers2 = List(1,2,3);
  
  val objects1 : List[Any] = List[Any](1, "bla");
  val objects2 = List(1, "bla");

Classes and Methods

  class Dog() {
    def bark1 = println("bark");

    def bark2 = {
      println("bark");
    }

    def bark3: Unit = {
      println("bark");
    }

    def bark4() = println("bark");
  }

  val dog = new Dog();
  dog.bark1;
  dog.bark2;
  dog.bark3;
  dog.bark4;
  dog.bark4();

Vals, Vars, Attributes and Contructors

  class Person(var name: String, val weight: Int) {
    var age: Int = 0;
  }

  val person = new Person("Anna", 100);

  println(person.name);
  println(person.age);
  println(person.weight);

  person.name = "Horst";
  person.age = 30;
  // Scala Compiler ignoriert fachliche Fehler
  
  // person.weight = 50; geht nicht

  println(person.name);
  println(person.age);
  println(person.weight);