From 92fc8b32ddb824cd69988f85488ff3013fbccd87 Mon Sep 17 00:00:00 2001 From: LMnet Date: Wed, 17 Apr 2019 17:04:13 +0700 Subject: [PATCH] Added collectFirst to Chain and NonEmptyChain --- core/src/main/scala/cats/data/Chain.scala | 17 +++++++++++++++++ .../main/scala/cats/data/NonEmptyChain.scala | 6 ++++++ 2 files changed, 23 insertions(+) diff --git a/core/src/main/scala/cats/data/Chain.scala b/core/src/main/scala/cats/data/Chain.scala index aa229dc9ba..b4611e81f9 100644 --- a/core/src/main/scala/cats/data/Chain.scala +++ b/core/src/main/scala/cats/data/Chain.scala @@ -145,6 +145,23 @@ sealed abstract class Chain[+A] { else acc } + /** + * Finds the first element of this `Chain` for which the given partial + * function is defined, and applies the partial function to it. + */ + final def collectFirst[B](pf: PartialFunction[A, B]): Option[B] = { + var result: Option[B] = None + foreachUntil { a => + // trick from TraversableOnce, used to avoid calling both isDefined and apply (or calling lift) + val x = pf.applyOrElse(a, sentinel) + if (x.asInstanceOf[AnyRef] ne sentinel) { + result = Some(x.asInstanceOf[B]) + true + } else false + } + result + } + /** * Remove elements not matching the predicate */ diff --git a/core/src/main/scala/cats/data/NonEmptyChain.scala b/core/src/main/scala/cats/data/NonEmptyChain.scala index 9aad230469..2d7eec0fe9 100644 --- a/core/src/main/scala/cats/data/NonEmptyChain.scala +++ b/core/src/main/scala/cats/data/NonEmptyChain.scala @@ -239,6 +239,12 @@ class NonEmptyChainOps[A](private val value: NonEmptyChain[A]) extends AnyVal { */ final def collect[B](pf: PartialFunction[A, B]): Chain[B] = toChain.collect(pf) + /** + * Finds the first element of this `NonEmptyChain` for which the given partial + * function is defined, and applies the partial function to it. + */ + final def collectFirst[B](pf: PartialFunction[A, B]): Option[B] = toChain.collectFirst(pf) + /** * Filters all elements of this chain that do not satisfy the given predicate. */