Skip to content

Commit

Permalink
Make Optional an IterableOnce
Browse files Browse the repository at this point in the history
So that we can:
```
def get(a: A): Optional[B] = ...
val list: List[A] = ...
val result: List[B] = list.flatMap(get)
```
  • Loading branch information
guizmaii committed Nov 14, 2024
1 parent 892210c commit e55c403
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -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))
},
)

}
11 changes: 9 additions & 2 deletions core/shared/src/main/scala/zio/prelude/data/Optional.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package zio.prelude.data

import zio.Chunk
import scala.IterableOnce

import scala.language.implicitConversions

Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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 {
Expand Down

0 comments on commit e55c403

Please sign in to comment.