Add TraverseFilter.mapAccumulateFilter
If Traverse has mapAccumulate, why don't TraverseFilter has mapAccumulateFilter?
Now it has. I implement method itself (almost fully copied from mapAccumulate, changing traverse to traverseFilter), syntax ops, and tests (almost fully copied from mapAccumulate, adjusting fn signature)
There is no override of mapAccumulate for Seq, so should it be added with mapAccumulateFilter through StaticMethods.mapAccumulateFilterFromStrictFunctorFilter?
There is no override of
mapAccumulatefor Seq, so should it be added withmapAccumulateFilterthroughStaticMethods.mapAccumulateFilterFromStrictFunctorFilter?
Same for LazyList and Stream
Bikeshed question: why
mapAccumulateFiltervsmapFilterAccumulate?
I just added "Filter"-suffix after original method name from Traverse, same as in traverse → traverseFilter and sequence → sequenceFilter
I have no opinion here, I don't mind both
There is no override of mapAccumulate for Seq, so should it be added with mapAccumulateFilter through StaticMethods.mapAccumulateFilterFromStrictFunctorFilter?
I think it can be addressed in a separate follow-up PR, just to avoid blowing up the scope of this one.
- Bikeshed question: why mapAccumulateFilter vs mapFilterAccumulate? I think I prefer the latter.
- I just added "Filter"-suffix after original method name from Traverse, same as in traverse → traverseFilter and sequence → sequenceFilter
We just get to decide, whether the new method is likely mapFilter + Accumulate or mapAccumulate + Filter 😄
As a bit more crazy idea (maybe not that crazy though): we can add two functions instead:
def mapAccumulateFilter[S, A, B](init: S, fa: F[A])(f: (S, A) => (S, Option[B])): (S, F[B])
def mapFilterAccumulate[S, A, B](init: S, fa: F[A])(f: (S, A) => Option[(S, B)]): (S, F[B])
The former always does accumulate regardless of filter, hence the name. The latter always does filter first, then accumulate if not filtered out.
Of course, we can implement mapFilterAccumulate in terms of mapAccumulateFilter, e.g.:
def mapFilterAccumulate[S, A, B](init: S, fa: F[A])(f: (S, A) => Option[(S, B)]): (S, F[B]) =
mapAccumulateFilter(init, fa) { (s1, a) =>
f(s1, a) match {
case (s2, Some(b)) => Some((s2, b))
case (_, None) => None // drop `S` from this iteration
}
}
However both functions can come handy under certain circumstances. (sorry if my snippet is incorrect – it is beyond 1 am already and I am gravily sleepy)
Moreover, even more important – it could help up to avoid choosing between two really good names and just move on with this PR :)
Of course, we can implement
mapFilterAccumulatein terms ofmapAccumulateFilter, e.g.:def mapFilterAccumulate[S, A, B](init: S, fa: F[A])(f: (S, A) => Option[(S, B)]): (S, F[B]) = mapAccumulateFilter(init, fa) { (s1, a) => f(s1, a) match { case (s2, Some(b)) => Some((s2, b)) case (_, None) => None // drop `S` from this iteration } }
This is implementation of mapAccumulateFilter in terms of mapFilterAccumulate. f pattern matching should be changed inside out:
f(s1, a) match
case Some((s2, b)) => (s2, Some(b))
case None => (s1, None)
This is implementation of mapAccumulateFilter in terms of mapFilterAccumulate. f pattern matching should be changed inside out:
Yes, thank you 😊
Anyway, mapFilterAccumulate looks like a special case for mapAccumulateFilter, which is more general. But it can come more handy when accumulation is not needed on entries where the condition does not hold.
@armanbilge – wdyt?
Hi there, just a check-up: where do we stand on this PR?