Skip to content

Instantly share code, notes, and snippets.

@betandr
Created February 2, 2015 18:09
Show Gist options
  • Save betandr/4aaad0ab750ea46ece9e to your computer and use it in GitHub Desktop.
Save betandr/4aaad0ab750ea46ece9e to your computer and use it in GitHub Desktop.
CoffeeMachine.scala
import scala.concurrent.future
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
import scala.util.Random
import scala.util.{Success, Failure}
class CoffeeMachine {
type CoffeeBeans = String
type GroundCoffee = String
case class Water(temperature: Int)
type Milk = String
type FrothedMilk = String
type Espresso = String
type Cappuccino = String
case class GrindingException(msg: String) extends Exception(msg)
case class FrothingException(msg: String) extends Exception(msg)
case class WaterBoilingException(msg: String) extends Exception(msg)
case class BrewingException(msg: String) extends Exception(msg)
def combine(espresso: Espresso, frothedMilk: FrothedMilk): Cappuccino = "cappuccino"
def grind(beans: CoffeeBeans): Future[GroundCoffee] = Future {
println(s"grinding '$beans'...")
Thread.sleep(Random.nextInt(2000))
if (beans == "baked beans") throw GrindingException("are you joking?")
println("finished grinding...")
s"ground coffee of $beans"
}
def heatWater(water: Water): Future[Water] = Future {
println("heating water...")
Thread.sleep(Random.nextInt(2000))
println("it's hot!")
water.copy(temperature = 85)
}
def frothMilk(milk: Milk): Future[FrothedMilk] = Future {
println(s"frothing $milk...")
Thread.sleep(Random.nextInt(2000))
//if (milk contains "milk") throw FrothingException(s"you can only froth types of milk, not $milk")*/
println("shutting down milk frother")
s"frothed $milk"
}
def brew(coffee: GroundCoffee, heatedWater: Water): Future[Espresso] = Future {
println(s"brewing $coffee")
Thread.sleep(Random.nextInt(2000))
println("it's brewed!")
"espresso"
}
def prepareCappuccinoSequentially(): Future[Cappuccino] = {
for {
ground <- grind("arabica beans")
water <- heatWater(Water(20))
foam <- frothMilk("milk")
espresso <- brew(ground, water)
} yield combine(espresso, foam)
}
def prepareCappuccino(): Future[Cappuccino] = {
val groundCoffee = grind("arabica beans")
val heatedWater = heatWater(Water(20))
val frothedMilk = frothMilk("milk")
for {
ground <- groundCoffee
water <- heatedWater
foam <- frothedMilk
espresso <- brew(ground, water)
} yield combine(espresso, foam)
}
}
object CoffeeMachine extends App {
val maker = new CoffeeMachine
var start = System.currentTimeMillis()
maker.prepareCappuccino.onComplete {
case Success(coffee) => {
val end = System.currentTimeMillis()
println(s"You got $coffee in " + (end - start) + " ms")
}
case Failure(ex) => println(ex)
}
start = System.currentTimeMillis()
maker.prepareCappuccinoSequentially.onComplete {
case Success(coffee) => {
val end = System.currentTimeMillis()
println(s"You got $coffee in " + (end - start) + " ms")
}
case Failure(ex) => println(ex)
}
Thread.sleep(20000)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment