Kotlin:通过并使用2参数函数?
我正在尝试在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
在映射到列表上时识别case标志?
谢谢!
编辑:上面的情况是以下的简化版本,它不工作…
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) }
这里有几个问题:
-
你的目标在这里是矛盾的 – 你要
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()) }
你原来的代码(借用者)其实非常接近成功,所以我会忽略你的简化版本。 你刚刚得到一行错误:
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)})
由于伴侣对象的成员可以用主类型的名称来调用,所以可以进一步简化为
val c = Borrower.findBorrower("borrower3", brs1, {Borrower.getName(it, 0)})