I wrote a combined map-and-find function that applies a function to an Iterable and returns the first mapped result for which a predicate is true:
implicit class EnhancedIterable[A, B[X] <: Iterable[X]](it: B[A]) {
def mapAndFind[B](f: A => B, p: B => Boolean): Option[B] = {
var result: Option[B] = None
for (value <- it if result.isEmpty) {
val r = f(value)
if (p(r))
result = Some(r)
}
result
}
}
The problem is I hit a compilation error when I try to use the function as expected:
val names = Seq("Jose", "Chris", "Carlos", "Stephan")
names.mapAndFind(
_.length,
_ > 5 // Error
)
Type mismatch, expected: (NotInferedB) => Boolean, actual: (Nothing) => Any
If I use a type hint though things compile fine:
names.mapAndFind(
_.length,
(len: Int) => len > 5
)
Why is type B
not inferred as Int
from f
?
Type inference in Scala flows between parameter lists, not inside them.
You can write:
implicit class EnhancedIterable[A, B[X] <: Iterable[X]](it: B[A]) {
def mapAndFind[B](f: A => B)(p: B => Boolean): Option[B] = {
var result: Option[B] = None
for (value <- it if result.isEmpty) {
val r = f(value)
if (p(r)) result = Some(r)
}
result
}
}
And then:
val names = Seq("Jose", "Chris", "Carlos", "Stephan")
names.mapAndFind(_.length)(_ > 5)
Yields:
Some(6)