Kotlin:传递并使用2参数函数?

时间:2017-06-08 19:23:08

标签: kotlin

我试图在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)
}

2 个答案:

答案 0 :(得分:5)

这里有几个问题:

  1. 您的目标在这里是矛盾的 - 您希望mapIt采用2-arg函数,但看起来您还试图执行caseName的部分应用,这当然会导致1-arg功能。

  2. 下划线不要在Kotlin做你想的(看起来你可能来自Scala背景?)。

  3. 看起来你想要这样的东西:

    // 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)})