Higher order functions have a parameter of either
- a function type or
- a function type with receiver.
We are used to filter and with from kotlin's stdlib:
@Test
fun `filter example`() {
val filtered = listOf("foo", "bar").filter {
it.startsWith("f")
}
assertThat(filtered).containsOnly("foo")
}
@Test
fun `with example`() {
val actual = with(StringBuilder()) {
append("foo")
append("bar")
toString()
}
assertThat(actual).isEqualTo("foobar")
}
While filter uses a function type parameter, with uses a function type parameter with receiver. So lambdas passed to filter use it to access the iterable's element, while lambdas passed to with use this to access the StringBuilder.
My question: Is there a rule of thumb, which style to use (it vs this), when I declare my own higher order function?
In other words: Why isn't filtering designed that way?
inline fun <T> Iterable<T>.filter2(predicate: T.() -> Boolean): List<T> = filter { it.predicate() }
If it were defined that way, we'd use it like so:
@Test
fun `filter2 function type with receiver`() {
val filtered = listOf("foo", "bar").filter2 {
// note: no use of it, but this
startsWith("f")
}
assertThat(filtered).containsOnly("foo")
}