Scala does not permit to create laze vars, only lazy vals. It make sense.
But I\'ve bumped on use case, where I\'d like to have similar capability. I need a lazy var
I've summarized all provided advices for building custom container:
object LazyVar {
class NotInitialized extends Exception
case class Update[+T]( update : () => T )
implicit def impliciţUpdate[T](update: () => T) : Update[T] = Update(update)
final class LazyVar[T] (initial : Option[Update[T]] = None ){
private[this] var cache : Option[T] = None
private[this] var data : Option[Update[T]] = initial
def put(update : Update[T]) : LazyVar[T] = this.synchronized {
data = Some(update)
this
}
def set(value : T) : LazyVar[T] = this.synchronized {
data = None
cache = Some(value)
this
}
def get : T = this.synchronized { data match {
case None => cache.getOrElse(throw new NotInitialized)
case Some(Update(update)) => {
val res = update()
cache = Some(res)
res
}
} }
def := (update : Update[T]) : LazyVar[T] = put(update)
def := (value : T) : LazyVar[T] = set(value)
def apply() : T = get
}
object LazyVar {
def apply[T]( initial : Option[Update[T]] = None ) = new LazyVar[T](initial)
def apply[T]( value : T) = {
val res = new LazyVar[T]()
res.set(value)
res
}
}
implicit def geţLazy[T](lazyvar : LazyVar[T]) : T = lazyvar.get
object Test {
val getInt1 : () => Int = () => {
print("GetInt1")
1
}
val getInt2 : () => Int = () => {
print("GetInt2")
2
}
val li : LazyVar[Int] = LazyVar()
li := getInt1
li := getInt2
val si : Int = li
}
}