我试图在Kotlin中学习函数式编程,并且很难使这段代码工作:
import java.util.*
fun caseName(br: String, c: Int): String {
if (c == 0) {
return br.toLowerCase()
} else {
return br.toUpperCase()
}
}
fun mapIt(ns: ArrayList<String>, f: (String, Int) -> String): List<String> {
val coll: List<String> = ns.map {it -> f(it, _)}
return coll
}
fun main(args: Array<String>) {
val names = arrayListOf("Joe", "Bill", "Murrary")
val cased = mapIt(names, (::caseName)(_, 0))
println(cased.first())
}
如何在列表上映射时让mapIt
识别案例标志?
谢谢!
编辑:上面的案例是以下的简化版本,它不起作用......
data class Borrower(val name: String, val maxBooks: Int) {
companion object {
fun getName(br: Borrower, c: Int): String {
if (c == 0) {
return br.name.toLowerCase()
} else {
return br.name.toUpperCase()
}
}
fun findBorrower(n: String, brs: ArrayList<Borrower>, f: (Borrower) -> String): Borrower? {
val coll: List<Borrower> = brs.filter { it -> f(it) == n }
if (coll.isEmpty()) {
return null
} else return coll.first()
}
}
}
fun main(args: Array<String>) {
val br1 = Borrower(name = "Borrower1", maxBooks = 1)
val br2 = Borrower(name = "Borrower2", maxBooks = 2)
val br3 = Borrower(name = "Borrower3", maxBooks = 3)
val br4 = Borrower(name = "borrower4", maxBooks = 4)
val br5 = Borrower(name = "BORROWER5", maxBooks = 5)
val brs1 = arrayListOf(br1, br2, br3, br4, br5)
val c = Borrower.findBorrower("borrower3", brs1, {Borrower.Companion::getName(it, 0)})
println(c)
}
答案 0 :(得分:5)
这里有几个问题:
您的目标在这里是矛盾的 - 您希望mapIt
采用2-arg函数,但看起来您还试图执行caseName
的部分应用,这当然会导致1-arg功能。
下划线不要在Kotlin做你想的(看起来你可能来自Scala背景?)。
看起来你想要这样的东西:
// f is a *single*-arg function
fun mapIt(ns: ArrayList<String>, f: (String) -> String): List<String> {
return ns.map(f)
}
fun main(args: Array<String>) {
val names = arrayListOf("Joe", "Bill", "Murrary")
val cased = mapIt(names, { caseName(it, 0) }) // Partial application
println(cased.first())
}
或者像这样:
// f is a two-arg function
fun mapIt(ns: ArrayList<String>, f: (String, Int) -> String): List<String> {
return ns.map { f(it, 0) }
}
fun main(args: Array<String>) {
val names = arrayListOf("Joe", "Bill", "Murrary")
val cased = mapIt(names, ::caseName)
println(cased.first())
}
答案 1 :(得分:1)
您的原始代码(Borrower
)实际上非常接近成功,因此我将忽略您的简化版本。你错了一行:
val c = Borrower.findBorrower("borrower3", brs1, {Borrower.Companion::getName(it, 0)})
^^
Why you are using double colon?
最后一个参数是一个lambda表达式,在lambda中使用函数引用是没有意义的,即使在scala中也是如此。只需使用普通的点就可以了。
val c = Borrower.findBorrower("borrower3", brs1, {Borrower.Companion.getName(it, 0)})
由于伴随对象的成员只能使用主要类型来调用&#39;名称,可以进一步简化为
val c = Borrower.findBorrower("borrower3", brs1, {Borrower.getName(it, 0)})