From bf9646e8249ffae387a2c4378f3a08330b7285e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Kozak?= Date: Tue, 9 Apr 2024 11:54:16 +0200 Subject: [PATCH] add `when`, `unless` extension methods to lazy opt --- .../scala/com/avsystem/commons/misc/Opt.scala | 19 +++++++++++++++++-- .../com/avsystem/commons/misc/OptTest.scala | 12 ++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/core/src/main/scala/com/avsystem/commons/misc/Opt.scala b/core/src/main/scala/com/avsystem/commons/misc/Opt.scala index 2f47749ec..5af628582 100644 --- a/core/src/main/scala/com/avsystem/commons/misc/Opt.scala +++ b/core/src/main/scala/com/avsystem/commons/misc/Opt.scala @@ -28,6 +28,20 @@ object Opt { def foreach[U](f: A => U): Unit = self filter p foreach f def withFilter(q: A => Boolean): WithFilter[A] = new WithFilter[A](self, x => p(x) && q(x)) } + + class LazyOptOps[A](private val opt: () => Opt[A]) extends AnyVal { + /** When a given condition is true, evaluates the `opt` argument and returns it. + * When the condition is false, `opt` is not evaluated and `Opt.Empty` is + * returned. + */ + def when(cond: Boolean): Opt[A] = if (cond) opt() else Opt.Empty + /** Unless a given condition is true, this will evaluate the `opt` argument and + * return it. Otherwise, `opt` is not evaluated and `Opt.Empty` is returned. + */ + @inline def unless(cond: Boolean): Opt[A] = when(!cond) + } + + implicit def lazyOptOps[A](opt: => Opt[A]): LazyOptOps[A] = new LazyOptOps(() => opt) } /** @@ -41,7 +55,8 @@ object Opt { * Please be aware of that tradeoff. */ final class Opt[+A] private(private val rawValue: Any) extends AnyVal with OptBase[A] with Serializable { - import Opt._ + + import Opt.* private def value: A = rawValue.asInstanceOf[A] @@ -140,7 +155,7 @@ final class Opt[+A] private(private val rawValue: Any) extends AnyVal with OptBa if (isEmpty) Iterator.empty else Iterator.single(value) @inline def toList: List[A] = - if (isEmpty) List() else new ::(value, Nil) + if (isEmpty) List() else new::(value, Nil) @inline def toRight[X](left: => X): Either[X, A] = if (isEmpty) Left(left) else Right(value) diff --git a/core/src/test/scala/com/avsystem/commons/misc/OptTest.scala b/core/src/test/scala/com/avsystem/commons/misc/OptTest.scala index 20e3557c6..3db90b4a7 100644 --- a/core/src/test/scala/com/avsystem/commons/misc/OptTest.scala +++ b/core/src/test/scala/com/avsystem/commons/misc/OptTest.scala @@ -66,4 +66,16 @@ class OptTest extends AnyFunSuite { val seq: Seq[Int] = Opt(5).mapOr(Nil, i => 0 until i) assert(seq == (0 until 5)) } + + test("Opt.{when, unless}") { + val opt = Opt(42) + + assert(opt.when(true) == opt) + assert(opt.when(false) == Opt.Empty) + assert(Opt(fail("Parameter should not be evaluated")).when(false) == Opt.Empty) + + assert(opt.unless(false) == opt) + assert(opt.unless(true) == Opt.Empty) + assert(Opt(fail("Parameter should not be evaluated")).unless(true) == Opt.Empty) + } }