trait Lazy[+T] extends Serializable
Wraps a lazily computed value. Also circumvents cycles during implicit search, or wrong implicit divergences as illustrated below, and holds the corresponding implicit value lazily.
The following implicit search sometimes fails to compile, because of a wrongly reported implicit divergence,
case class ListCC(list: List[CC]) case class CC(i: Int, s: String) trait TC[T] object TC { implicit def intTC: TC[Int] = ??? implicit def stringTC: TC[String] = ??? implicit def listTC[T](implicit underlying: TC[T]): TC[List[T]] = ??? implicit def genericTC[F, G](implicit gen: Generic.Aux[F, G], underlying: TC[G] ): TC[F] = ??? implicit def hnilTC: TC[HNil] = ??? implicit def hconsTC[H, T <: HList](implicit headTC: TC[H], tailTC: TC[T] ): TC[H :: T] = ??? } implicitly[TC[ListCC]] // fails with: diverging implicit expansion for type TC[ListCC]
This wrongly reported implicit divergence can be circumvented by wrapping some of the implicit values in
Lazy
,
case class ListCC(list: List[CC]) case class CC(i: Int, s: String) trait TC[T] object TC { implicit def intTC: TC[Int] = ??? implicit def stringTC: TC[String] = ??? implicit def listTC[T](implicit underlying: TC[T]): TC[List[T]] = ??? implicit def genericTC[F, G](implicit gen: Generic.Aux[F, G], underlying: Lazy[TC[G]] // wrapped in Lazy ): TC[F] = ??? implicit def hnilTC: TC[HNil] = ??? implicit def hconsTC[H, T <: HList](implicit headTC: Lazy[TC[H]], // wrapped in Lazy tailTC: TC[T] ): TC[H :: T] = ??? } implicitly[TC[ListCC]]
When looking for an implicit Lazy[TC[T]]
, the Lazy.mkLazy
macro will itself trigger the implicit search
for a TC[T]
. If this search itself triggers searches for types wrapped in Lazy
, these will be done
only once, their result put in a lazy val
, and a reference to this lazy val
will be returned as the corresponding
value. It will then wrap all the resulting values together, and return a reference to the first one.
E.g. with the above example definitions, when looking up for an implicit TC[ListCC]
, the returned tree roughly looks
like
TC.genericTC( Generic[ListCC], // actually, the tree returned by Generic.materialize, not written here for the sake of brevity Lazy { lazy val impl1: TC[List[CC] :: HNil] = TC.hconsTC( Lazy(impl2), TC.hnilTC ) lazy val impl2: TC[List[CC]] = TC.listTC(TC.genericTC( Generic[CC], // actually, the tree returned by Generic.materialize Lazy(impl1) // cycles to the initial TC[List[CC] :: HNil] )) impl1 } )
- Annotations
- @implicitNotFound("could not find Lazy implicit value of type ${T}")
- Alphabetic
- By Inheritance
- Lazy
- Serializable
- AnyRef
- Any
- Hide All
- Show All
- Public
- All
Abstract Value Members
- abstract val value: T
Concrete Value Members
- final def !=(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
- final def ##(): Int
- Definition Classes
- AnyRef → Any
- final def ==(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
- final def asInstanceOf[T0]: T0
- Definition Classes
- Any
- def clone(): AnyRef
- Attributes
- protected[java.lang]
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.CloneNotSupportedException]) @native()
- final def eq(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
- def equals(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef → Any
- def finalize(): Unit
- Attributes
- protected[java.lang]
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.Throwable])
- def flatMap[U](f: (T) => Lazy[U]): Lazy[U]
- final def getClass(): Class[_ <: AnyRef]
- Definition Classes
- AnyRef → Any
- Annotations
- @native()
- def hashCode(): Int
- Definition Classes
- AnyRef → Any
- Annotations
- @native()
- final def isInstanceOf[T0]: Boolean
- Definition Classes
- Any
- def map[U](f: (T) => U): Lazy[U]
- final def ne(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
- final def notify(): Unit
- Definition Classes
- AnyRef
- Annotations
- @native()
- final def notifyAll(): Unit
- Definition Classes
- AnyRef
- Annotations
- @native()
- final def synchronized[T0](arg0: => T0): T0
- Definition Classes
- AnyRef
- def toString(): String
- Definition Classes
- AnyRef → Any
- final def wait(): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.InterruptedException])
- final def wait(arg0: Long, arg1: Int): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.InterruptedException])
- final def wait(arg0: Long): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.InterruptedException]) @native()