Skip to main content
Version: 2.x

ScopedRef: Mutable Reference For Resources

ScopedRef is a resourceful version of Ref data type. So it is a Ref for resourceful effects.

Operations​

There are two basic operations: get and set:

  • ScopedRef#get returns the current value of the scoped ref.

  • ScopedRef#set sets the scoped ref to a new value by acquiring the new resource to create a new value of the scoped ref. Setting a new value releases the old resource automatically.

Construction​

The ScopedRef has two constructors:

object ScopedRef {
def make[A](a: => A): ZIO[Scope, Nothing, ScopedRef[A]] = ???
def fromAcquire[R, E, A](acquire: ZIO[R, E, A]): ZIO[R with Scope, E, ScopedRef[A]] = ???
}

So we have two options to create a ScopedRef:

  • ScopedRef.make creates a scoped ref from an ordinary value. We can use this constructor when we don't need to acquire a resource to create a value of the scoped ref, for example, when we have a constant value.

  • ScopedRef.fromAcquire creates a scoped ref from an effect that resourcefully produces a value.

note

ScopedRef is resourceful, so its lifetimes is scoped. Whenever we don't need it anymore, we can release it by using ZIO#scoped combinator.

Example​

Let's see how changing the value of a ScopedRef automatically releases the old resource:

import zio._

object MainApp extends ZIOAppDefault {
def run = for {
_ <- ZIO.unit
r1 = ZIO.acquireRelease(
ZIO
.debug("acquiring the first resource")
.as(5)
)(_ => ZIO.debug("releasing the first resource"))
r2 = ZIO.acquireRelease(
ZIO
.debug("acquiring the second resource")
.as(10)
)(_ => ZIO.debug("releasing the second resource"))
sref <- ScopedRef.fromAcquire(r1)
_ <- sref.get.debug
_ <- sref.set(r2)
_ <- sref.get.debug
} yield ()
}

The output:

acquiring the first resource
5
acquiring the second resource
releasing the first resource
10
releasing the second resource