Skip to content

Commit

Permalink
feat(boundaries): add a result boundary
Browse files Browse the repository at this point in the history
  • Loading branch information
tassiluca committed Jan 2, 2024
1 parent 79455d8 commit ae55547
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 27 deletions.
26 changes: 0 additions & 26 deletions src/main/scala/io/github/tassiLuca/boundaries/BOptional.scala

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@ package io.github.tassiLuca.boundaries

import scala.util.boundary
import scala.util.boundary.break
import optional.*

object BoundaryExamples extends App:

def firstIndex[T](xs: List[T], elem: T): Int =
boundary:
for (x, i) <- xs.zipWithIndex do if x == elem then break(i)
-1

def firstColumn[T](xss: List[List[T]]): Option[List[T]] =
optional:
xss.map(_.headOption.?)
22 changes: 22 additions & 0 deletions src/main/scala/io/github/tassiLuca/boundaries/ResultExamples.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package io.github.tassiLuca.boundaries

import io.github.tassiLuca.boundaries.result.{Ok, Result, Error}

object ResultExamples extends App:

type User = String
type Address = String

def getUser(id: String): Result[User] =
Ok("Mario Rossi")

def getAddress(user: User): Result[Address] =
Error("The user doesn't exists")

def together(): Result[String] =
result:
val user = getUser("101").?
val address = getAddress(user).?
user + address

println(together())
12 changes: 12 additions & 0 deletions src/main/scala/io/github/tassiLuca/boundaries/optional.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package io.github.tassiLuca.boundaries

import scala.util.boundary
import scala.util.boundary.{Label, break}

object optional:
inline def apply[T](inline body: Label[None.type] ?=> T): Option[T] =
boundary(Some(body))

extension [T](o: Option[T])
inline def ?(using label: Label[None.type]): T =
o.getOrElse(break(None))
18 changes: 18 additions & 0 deletions src/main/scala/io/github/tassiLuca/boundaries/result.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.github.tassiLuca.boundaries

import scala.util.boundary
import scala.util.boundary.{Label, break}

object result:

sealed trait Result[+T]
case class Ok[+T](t: T) extends Result[T]
case class Error(e: String) extends Result[Nothing]

inline def apply[T](inline body: Label[Error] ?=> T): Result[T] =
boundary(Ok(body))

extension [T](r: Result[T])
inline def ?(using Label[Error]): T = r match
case Ok(t) => t
case e @ Error(_) => break(e)
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.github.tassiLuca.boundaries

import io.github.tassiLuca.boundaries.BoundaryExamples.firstIndex
import io.github.tassiLuca.boundaries.BoundaryExamples.{firstColumn, firstIndex}
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers.shouldBe

Expand All @@ -9,3 +9,8 @@ class BoundaryExamplesTest extends AnyFlatSpec:
firstIndex(List(1, 2, 3, 4), 4) shouldBe 3
firstIndex(List(1, 2, 3, 4), 0) shouldBe -1
}

"BoundaryExamples.firstColumn" should "return a List with the first element of each List given in input" in {
firstColumn(List(List(1, 2, 3), List(3))) shouldBe Some(List(1, 3))
firstColumn(List(List(), List(1))) shouldBe None
}

0 comments on commit ae55547

Please sign in to comment.