Skip to content

Instantly share code, notes, and snippets.

@Ostkontentitan
Created March 19, 2018 15:12
Show Gist options
  • Save Ostkontentitan/d82ca68c46ef8a56d29f2b7c2ce1160f to your computer and use it in GitHub Desktop.
Save Ostkontentitan/d82ca68c46ef8a56d29f2b7c2ce1160f to your computer and use it in GitHub Desktop.
Some drafts of a DSL for coffee making written in Kotlin for presentation purposes.
// DOMAIN OBJECTS
interface Blend {
val intensity: Intensity
val flavours: Set<Flavour>
}
object EspressoBlend : Blend {
override val intensity: Intensity = 10
override val flavours: Set<Flavour> = setOf(Flavour.I_AM_AWAKE)
}
interface LiquidType
object Water : LiquidType
object Milk : LiquidType
object Coffee : LiquidType
val Int.oz get() = this
val Int.degree get() = this
typealias Ounce = Int
typealias Degree = Int
data class Liquid(val type: LiquidType, val amount: Ounce)
data class Portafilter(val blend: Blend, val amount: Ounce)
infix fun Ounce.of(liquidType: LiquidType) = Liquid(liquidType, this)
infix fun Ounce.of(blend: Blend) = Portafilter(blend, this)
sealed class Container(val size: Ounce)
object Glass : Container(3.oz)
object Mug : Container(6.oz)
object SteamingPitcher : Container(4.oz)
enum class Flavour {
WOW, I_AM_AWAKE
}
typealias Intensity = Int
data class Beverage(val liquids: Set<Liquid>,
val container: Container,
val flavours: Set<Flavour> = emptySet(),
val intensity: Intensity = 0)
class ContainerOverflowException : Exception()
// DSL INTERFACE
class Barista {
infix fun pull(portafilter: Portafilter) = PullAction(portafilter.amount, portafilter.blend)
infix fun pour(beverage: Beverage) = PourAction(beverage)
infix fun pour(liquid: Liquid) = PourLiquidIntoAction(liquid)
infix fun steam(beverage: Beverage) = SteamAction(beverage)
data class PullAction(val amount: Ounce, val blend: Blend) {
infix fun into(container: Container): Beverage = TODO()
}
data class PourAction(val beverage: Beverage) {
infix fun into(other: Beverage): Beverage = TODO()
}
data class PourLiquidIntoAction(val liquid: Liquid) {
infix fun into(container: Container): Beverage = TODO()
}
data class SteamAction(val beverage: Beverage) {
infix fun until(condition: SteamAction.() -> Boolean): Unit = TODO()
val foamy: Boolean = TODO()
fun temperature(temp: Degree): Boolean = TODO()
}
}
fun barista(instructionsBlock: Barista.() -> Beverage): Beverage {
return instructionsBlock.invoke(Barista())
}
// COFFEE RECIPES
fun espresso() = barista {
pull (3.oz of EspressoBlend) into Glass
}
fun makeAmericano() = barista {
val espresso = pull (3.oz of EspressoBlend) into Glass
val hotWater = pour(3.oz of Water) into Mug
pour(espresso) into hotWater
}
fun cappuccino() = barista {
val milk = pour(4.oz of Milk) into SteamingPitcher
steam(milk) until { foamy and temperature(65.degree) }
val espresso =
pull (3.oz of EspressoBlend) into Mug
espresso.copy(intensity = 7, flavours = espresso.flavours + Flavour.I_AM_AWAKE)
pour(milk) into espresso
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment