From 9404d01ce1bc051da5f26166e15cce6a61deac7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabi=C3=A1n=20Heredia=20Montiel?= Date: Sat, 2 Sep 2023 17:52:31 -0600 Subject: [PATCH] performance changes --- .../dev/librecybernetics/data/Bijection.scala | 4 +- .../librecybernetics/data/FnBijection.scala | 46 ++++++------------- .../librecybernetics/data/MapBijection.scala | 17 ++++--- .../librecybernetics/data/PFnBijection.scala | 44 +++++------------- .../data/MapBijectionSpec.scala | 4 +- 5 files changed, 38 insertions(+), 77 deletions(-) diff --git a/core/src/main/scala/dev/librecybernetics/data/Bijection.scala b/core/src/main/scala/dev/librecybernetics/data/Bijection.scala index d090f77..3c09d6c 100644 --- a/core/src/main/scala/dev/librecybernetics/data/Bijection.scala +++ b/core/src/main/scala/dev/librecybernetics/data/Bijection.scala @@ -49,7 +49,5 @@ trait Bijection[F[_, _], A, B]: def flip: F[B, A] // Combine - def ++[ - M[_]: [M[_]] =>> MonadError[M, Bijection.Error] - ](other: F[A, B]): M[F[A, B]] + def ++(other: F[A, B]): F[A, B] end Bijection diff --git a/core/src/main/scala/dev/librecybernetics/data/FnBijection.scala b/core/src/main/scala/dev/librecybernetics/data/FnBijection.scala index ee4f98a..56cf401 100644 --- a/core/src/main/scala/dev/librecybernetics/data/FnBijection.scala +++ b/core/src/main/scala/dev/librecybernetics/data/FnBijection.scala @@ -7,45 +7,25 @@ import cats.MonadError case class FnBijection[A, B]( forwardFn: A => B, reverseFn: B => A -) extends Bijection[FnBijection, A, B]: +) extends Bijection[FnBijection, A, B] { self => // Properties def isDefined(a: A): Boolean = Try(forwardFn(a)).isSuccess // Access - def apply(a: A): Option[B] = Try(forwardFn(a)).toOption + def apply(a: A): Option[B] = Try(forwardFn(a)).toOption + def reverse(b: B): Option[A] = Try(reverseFn(b)).toOption // Transform - def flip: FnBijection[B, A] = FnBijection(reverseFn, forwardFn) + override lazy val flip: FnBijection[B, A] = new FnBijection(self.reverseFn, self.forwardFn) { + override lazy val flip: FnBijection[A, B] = self + } // Combine - @SuppressWarnings(Array("org.wartremover.warts.Throw")) - def ++[F[_]: [F[_]] =>> MonadError[F, Bijection.Error]]( - other: FnBijection[A, B] - ): F[FnBijection[A, B]] = - MonadError[F, Bijection.Error].pure { - FnBijection( - forwardFn = a => - (apply(a), other(a)) match - case (Some(b), None) => b - case (None, Some(b)) => b - - case (Some(b1), Some(b2)) if b1 == b2 => b1 - - case (_, _) => - throw new NoSuchElementException() - end match - , - reverseFn = b => - (reverse(b), other.reverse(b)) match - case (Some(a), None) => a - case (None, Some(a)) => a - - case (Some(a1), Some(a2)) if a1 == a2 => a1 - - case (_, _) => - throw new NoSuchElementException() - end match - ) - } -end FnBijection + @SuppressWarnings(Array("org.wartremover.warts.OptionPartial")) + def ++(other: FnBijection[A, B]): FnBijection[A, B] = + FnBijection( + forwardFn = a => other.apply(a).orElse(this.apply(a)).get, + reverseFn = b => other.reverse(b).orElse(this.reverse(b)).get + ) +} diff --git a/core/src/main/scala/dev/librecybernetics/data/MapBijection.scala b/core/src/main/scala/dev/librecybernetics/data/MapBijection.scala index 2106a7f..a05120d 100644 --- a/core/src/main/scala/dev/librecybernetics/data/MapBijection.scala +++ b/core/src/main/scala/dev/librecybernetics/data/MapBijection.scala @@ -10,7 +10,7 @@ import cats.{MonadError, Traverse} case class MapBijection[A, B] private[data] ( forwardMap: Map[A, B], reverseMap: Map[B, A] -) extends Bijection[MapBijection, A, B]: +) extends Bijection[MapBijection, A, B] { self => // Properties override def isDefined(a: A): Boolean = forwardMap.contains(a) @@ -31,11 +31,13 @@ case class MapBijection[A, B] private[data] ( end size // Access - override def apply(a: A): Option[B] = forwardMap.get(a) + override def apply(a: A): Option[B] = forwardMap.get(a) + override def reverse(b: B): Option[A] = reverseMap.get(b) def iterable: Iterable[(A, B)] = forwardMap.iterator.to(Iterable) - def keySet: Set[A] = forwardMap.keySet + + def keySet: Set[A] = forwardMap.keySet // Transform override def flip: MapBijection[B, A] = new MapBijection[B, A](reverseMap, forwardMap) @@ -70,8 +72,11 @@ case class MapBijection[A, B] private[data] ( ): F[MapBijection[A, B]] = Traverse[T].foldM(iterable, this)(_ + _) - override def ++[F[_]: [F[_]] =>> MonadError[F, Bijection.Error]](other: MapBijection[A, B]): F[MapBijection[A, B]] = - this ++ other.iterable + override def ++(other: MapBijection[A, B]): MapBijection[A, B] = + MapBijection( + forwardMap ++ other.forwardMap, + reverseMap ++ other.reverseMap + ) end ++ @targetName("remove") @@ -83,7 +88,7 @@ case class MapBijection[A, B] private[data] ( @targetName("removeAll") infix def --(i: IterableOnce[A]): MapBijection[A, B] = i.iterator.foldLeft(this)(_ - _) -end MapBijection +} object MapBijection: def empty[A, B]: MapBijection[A, B] = diff --git a/core/src/main/scala/dev/librecybernetics/data/PFnBijection.scala b/core/src/main/scala/dev/librecybernetics/data/PFnBijection.scala index 31aa5ff..a011dae 100644 --- a/core/src/main/scala/dev/librecybernetics/data/PFnBijection.scala +++ b/core/src/main/scala/dev/librecybernetics/data/PFnBijection.scala @@ -5,46 +5,24 @@ import cats.MonadError case class PFnBijection[A, B]( forwardPFn: PartialFunction[A, B], reversePFn: PartialFunction[B, A] -) extends Bijection[PFnBijection, A, B]: +) extends Bijection[PFnBijection, A, B] { self => // Properties override def isDefined(a: A): Boolean = forwardPFn.isDefinedAt(a) // Access - override def apply(a: A): Option[B] = forwardPFn.unapply(a) - override def reverse(b: B): Option[A] = reversePFn.unapply(b) + inline override def apply(a: A): Option[B] = forwardPFn.unapply(a) + + inline override def reverse(b: B): Option[A] = reversePFn.unapply(b) // Transform - override def flip: PFnBijection[B, A] = PFnBijection(reversePFn, forwardPFn) + override lazy val flip: PFnBijection[B, A] = new PFnBijection(reversePFn, forwardPFn) { + override lazy val flip: PFnBijection[A, B] = self + } // Combine - override def ++[F[_]: [F[_]] =>> MonadError[F, Bijection.Error]]( - other: PFnBijection[A, B] - ): F[PFnBijection[A, B]] = MonadError[F, Bijection.Error].pure { + override def ++(other: PFnBijection[A, B]): PFnBijection[A, B] = PFnBijection[A, B]( - forwardPFn = { - case a if apply(a).isDefined && other(a).isEmpty => - forwardPFn(a) - case a if apply(a).isEmpty && other(a).isDefined => - other.forwardPFn(a) - - case a - if apply(a).isDefined && - other(a).isDefined && - apply(a) == other(a) => - forwardPFn(a) - }: PartialFunction[A, B], - reversePFn = { - case b if reverse(b).isDefined && other.reverse(b).isEmpty => - reversePFn(b) - case b if reverse(b).isEmpty && other.reverse(b).isDefined => - other.reversePFn(b) - - case b - if reverse(b).isDefined && - other.reverse(b).isDefined && - reverse(b) == other.reverse(b) => - reversePFn(b) - }: PartialFunction[B, A] + forwardPFn = other.forwardPFn.orElse(this.forwardPFn), + reversePFn = other.reversePFn.orElse(this.reversePFn) ) - } -end PFnBijection +} diff --git a/core/src/test/scala/dev/librecybernetics/data/MapBijectionSpec.scala b/core/src/test/scala/dev/librecybernetics/data/MapBijectionSpec.scala index 6efde05..bcd8647 100644 --- a/core/src/test/scala/dev/librecybernetics/data/MapBijectionSpec.scala +++ b/core/src/test/scala/dev/librecybernetics/data/MapBijectionSpec.scala @@ -35,8 +35,8 @@ class MapBijectionSpec extends AnyWordSpec: val Right(secondBijection): Either[Bijection.Error, MapBijection[Char, Int]] = MapBijection('d' -> 4, 'e' -> 5, 'f' -> 6): @unchecked - val Right(concat): Either[Bijection.Error, MapBijection[Char, Int]] = - bijection ++ secondBijection: @unchecked + + val concat: MapBijection[Char, Int] = bijection ++ secondBijection concat.size shouldBe 6 }