How to check if a lazy val is initialized without initializing it?
You can do something like this:
object TheApp {
private var _optionalSubsystemInitialized = false
def optionalSubsystemInitialized = _optionalSubsystemInitialized
lazy val optionalSubsystem = {
_optionalSubsystemInitialized = true
subsystem
}
}
Whether is it really appropriate to have such side effects in the initialization code of a lazy val
is another question.
This isn't really an answer to your question, and I hate when people do this, but I'm going to do it anyway. I think the best response is: A lazy val isn't appropriate for this, so define a type that does support what you need.
You'll have to refer to the variable as optionalSubsystem()
rather than optionalSubsystem
, but that's A Good Thing, because with the design you want, obtaining that reference is an observably side-effecting procedure.
class Lazy[A](f: => A, private var option: Option[A] = None) {
def apply(): A = option match {
case Some(a) => a
case None => val a = f; option = Some(a); a
}
def toOption: Option[A] = option
}
scala> val optionalSubsystem = new Lazy { "a" }
optionalSubsystem: Lazy[java.lang.String] = Lazy@1210267
scala> optionalSubsystem.toOption.isDefined
res1: Boolean = false
scala> optionalSubsystem()
res2: java.lang.String = a
scala> optionalSubsystem.toOption.isDefined
res12: Boolean = true
Edit - Here's another revision with some modifications thanks to Tomas Mikula:
import scala.language.implicitConversions
object Lazy {
def lazily[A](f: => A): Lazy[A] = new Lazy(f)
implicit def evalLazy[A](l: Lazy[A]): A = l()
}
class Lazy[A] private(f: => A) {
private var option: Option[A] = None
def apply(): A = option match {
case Some(a) => a
case None => val a = f; option = Some(a); a
}
def isEvaluated: Boolean = option.isDefined
}
This lets you write lazily { ... }
instead of new Lazy { ... }
, and optionalSubsystem
instead of optionalSubsystem()
.
scala> import Lazy._
import Lazy._
scala> val optionalSubsystem = lazily { "a" }
optionalSubsystem: Lazy[String] = Lazy@3d0d54
scala> optionalSubsystem.isEvaluated
res0: Boolean = false
scala> optionalSubsystem: String
res1: String = a
scala> optionalSubsystem.isEvaluated
res2: Boolean = true