正如 JB Nizet 所提到的,这不是特定于过滤的,而是标准的 Kotlin 语法。如果你调用一个以 lambda 作为最后一个参数的函数,例如:
list.map({ size -> size * 2 })
然后你可以把lambda移到括号外:
list.map(){ size -> size * 2 }
(这主要是为了允许看起来像新语言语法的函数。但它通常很有用。)并且如果其中没有任何内容,您可以完全省略括号:
list.map{ size -> size * 2 }
另外,如果一个 lambda 表达式只有一个参数(并且编译器可以推断其类型),那么您可以将其称为 it 而不是显式命名:
list.map{ it * 2 }
所有四种形式的含义完全相同:它们使用 lambda 调用 map() 函数。 (您会经常看到这类语法快捷方式;它们有助于使代码更易于阅读。)
好的,进入你的代码:
您的第一行有效,但您的谓词函数需要一些调整才能编译。签名很好,但如果没有大括号,定义将无法工作。 (在 Scala 和 Java 中,箭头是区分的部分;但我们刚刚看到如何在 Kotlin 中省略它,因此每个 lambda 都必须有大括号。)
另外,您还没有定义firstName 或prefix。我将假设我们可以忽略前者,并将后者作为参数提供。稍微简化一下,得到:
fun getSimplePredicate(prefix: String): (String) -> Boolean
= { it.startsWith(prefix) }
并且通过这些调整,您确实可以使用它来提供用于过滤的谓词,例如:
listOf("john", "dave").filter(getSimplePredicate("j"))
(请注意,这次没有花括号,因为我们没有在这一行中创建 lambda - 函数已经完成了。)
当然,在这种情况下,根据您的第一个示例,直接提供 lambda 实际上更简单!但这说明了原理。
还有另一个值得一提的选项,即函数引用。如果您已经有一个可以完成这项工作的函数,则不需要将它放在 lambda 中,但可以使用 :: 表示法直接引用它。例如:
fun hasValidPrefix(s: String) = s.startsWith("j")
listOf("john", "dave").filter(::hasValidPrefix)
这只有在参数类型兼容时才有效,但它稍微简单一些(并且可以生成更高效的字节码)。
所有这些都解释了in the Kotlin docs。