diff --git a/core-tests/shared/src/test/scala/zio/prelude/data/OptionalSpec.scala b/core-tests/shared/src/test/scala/zio/prelude/data/OptionalSpec.scala new file mode 100644 index 000000000..4b3ad5138 --- /dev/null +++ b/core-tests/shared/src/test/scala/zio/prelude/data/OptionalSpec.scala @@ -0,0 +1,21 @@ +package zio.prelude.data + +import zio.Scope +import zio.prelude.ZIOBaseSpec +import zio.prelude.data.Optional +import zio.test.{Spec, TestEnvironment, assertTrue} + +object OptionalSpec extends ZIOBaseSpec { + + override def spec: Spec[TestEnvironment with Scope, Any] = + suite("Optional")( + test("is an IterableOnce") { + def get(a: Int): Optional[Long] = Optional.Present(a.toLong) + val list: List[Int] = List(1, 2, 3) + val result: List[Long] = list.flatMap(get) + + assertTrue(result == List(1L, 2L, 3L)) + }, + ) + +} diff --git a/core/shared/src/main/scala/zio/prelude/data/Optional.scala b/core/shared/src/main/scala/zio/prelude/data/Optional.scala index c9ad9282b..f5c17e9c7 100644 --- a/core/shared/src/main/scala/zio/prelude/data/Optional.scala +++ b/core/shared/src/main/scala/zio/prelude/data/Optional.scala @@ -1,6 +1,7 @@ package zio.prelude.data import zio.Chunk +import scala.IterableOnce import scala.language.implicitConversions @@ -13,7 +14,7 @@ import scala.language.implicitConversions * The only difference between this type and [[scala.Option]] is that there is an implicit * conversion defined from `A`` to `Optional[A]`, and from `Option[A]`` to `Optional[A]`. */ -sealed trait Optional[+A] { self => +sealed trait Optional[+A] extends IterableOnce[A] { self => val isEmpty: Boolean val isDefined: Boolean val nonEmpty: Boolean @@ -122,7 +123,7 @@ sealed trait Optional[+A] { self => final def orElse[B >: A](alternative: => Optional[B]): Optional[B] = if (isEmpty) alternative else this - final def iterator: Iterator[A] = + override final def iterator: Iterator[A] = self match { case Optional.Present(get) => Iterator.single(get) case Optional.Absent => Iterator.empty @@ -145,6 +146,12 @@ sealed trait Optional[+A] { self => case Optional.Present(get) => Vector(get) case Optional.Absent => Vector.empty } + + /** + * Copied from [[Option.knownSize]] + */ + override final def knownSize: Int = if (isEmpty) 0 else 1 + } object Optional {