Skip to content

Instantly share code, notes, and snippets.

@aposwolsky
Created March 15, 2013 21:23
Show Gist options
  • Save aposwolsky/5173202 to your computer and use it in GitHub Desktop.
Save aposwolsky/5173202 to your computer and use it in GitHub Desktop.
Priming with traits...
package demo
class Bar(id: Int) { def name = "Bar" + id }
class Baz(id: Int) { def name = "Baz" + id }
sealed abstract class Foo {
def id: Int
def barId: Int
def bazId: Int
}
trait HasBarPrimed { def bar: Option[Bar] }
trait HasBazPrimed { def baz: Option[Baz] }
// PrivateHiddenRealFoo has everything as our current models do...
case class PrivateHiddenRealFoo(id: Int, barId: Int, bazId: Int)
extends Foo with HasBarPrimed with HasBazPrimed {
var isBarCalced = false
var barObj: Option[Bar] = None
def bar: Option[Bar] = {
if (isBarCalced) {
barObj
} else {
throw new Exception("Attempting to access unprimed resource!... impossible!")
}
}
var isBazCalced = false
var bazObj: Option[Baz] = None
def baz: Option[Baz] = {
if (isBazCalced) {
bazObj
} else {
throw new Exception("Attempting to access unprimed resource!... impossible!")
}
}
}
object FooBuilder {
def build(id: Int, barId: Int, bazId: Int): Foo = new PrivateHiddenRealFoo(id, barId, bazId)
}
object Demos {
import Priming._
def main(argv: Array[String]) = {
val xs: List[Foo] = List(FooBuilder.build(101, 201, 301), FooBuilder.build(102, 202, 302))
println("Priming demo...")
//xs.foreach(x => println(x.bar.get.name)) -- failed with compile error! yay!
xs.primeBar.foreach(x => println(x.bar.get.name))
println()
xs.primeBaz.foreach(x => println(x.baz.get.name))
println()
xs.primeBar.primeBaz.foreach(x => println(x.bar.get.name + x.baz.get.name))
println()
}
}
object Priming {
// The invariant requires that Foo is a sealed class, so that we can guarantee that if we are passed a T <: Foo,
// it must be a PrivateHiddenRealFoo
class FooList[T <: Foo](xs: List[T]) {
def primeBar: List[T with HasBarPrimed] = {
val records = xs.asInstanceOf[List[PrivateHiddenRealFoo]]
records.foreach(x => {
if (!x.isBarCalced) {
x.isBarCalced = true
x.barObj = Some(new Bar(x.barId))
}
})
records.asInstanceOf[List[T with HasBarPrimed]]
}
def primeBaz: List[T with HasBazPrimed] = {
val records = xs.asInstanceOf[List[PrivateHiddenRealFoo]]
records.foreach(x => {
if (!x.isBazCalced) {
x.isBazCalced = true
x.bazObj = Some(new Baz(x.bazId))
}
})
records.asInstanceOf[List[T with HasBazPrimed]]
}
}
implicit def wrapFooList[T <: Foo](xs: List[T]): FooList[T] = new FooList(xs)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment