From 0ee9906c425d0b2c8dde39e4fca9d995ae7c95c2 Mon Sep 17 00:00:00 2001 From: Kailuo Wang Date: Mon, 20 Nov 2017 10:34:45 -0500 Subject: [PATCH] use the performance trick from traverseOnce --- core/src/main/scala/cats/Foldable.scala | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/core/src/main/scala/cats/Foldable.scala b/core/src/main/scala/cats/Foldable.scala index 5a46ea5716..246a6d3faa 100644 --- a/core/src/main/scala/cats/Foldable.scala +++ b/core/src/main/scala/cats/Foldable.scala @@ -214,10 +214,15 @@ import simulacrum.typeclass case Right(_) => None } - def collectFirst[A, B](fa: F[A])(pf: PartialFunction[A, B]): Option[B] = + def collectFirst[A, B](fa: F[A])(pf: PartialFunction[A, B]): Option[B] = { + //trick from TravsersableOnce + val sentinel: Function1[A, Any] = new scala.runtime.AbstractFunction1[A, Any]{ def apply(a: A) = this } foldRight(fa, Eval.now(Option.empty[B])) { (a, lb) => - if (pf.isDefinedAt(a)) Eval.now(Some(pf.apply(a))) else lb + val x = pf.applyOrElse(a, sentinel) + if (x.asInstanceOf[AnyRef] ne sentinel) Eval.now(Some(x.asInstanceOf[B])) + else lb }.value + } /** * Like `collectFirst` from `scala.collection.Traversable` but takes `A => Option[B]`