如何使用Kotlin将函数输出转换为Unit

时间:2017-11-18 19:57:48

标签: function return kotlin

我在Kotlin中有一个应该返回Unit的函数有麻烦,但是由于使用了另一个返回布尔值的函数,所以存在类型不匹配。

这是一个人为的例子:

fun printAndReturnTrue(bar: Int): Boolean {
    println(bar)
    return true
}

fun foo(bar: Int): Unit = when(bar) {
    0 -> println("0")
    else -> printAndReturnTrue(bar)
}

在这里,我实际上并不关心printAndReturnTrue返回布尔值的事实。我只想让foo执行副作用操作。但是编译器会警告类型不匹配:我的else应该返回Unit值。

有没有一种方法可以将值转换为Unit

我看到的最简单的解决方案是:

fun foo(bar: Int): Unit = when(bar) {
    0 -> println("0")
    else -> { 
        printAndReturnTrue(bar)
        Unit
    }
}

或:

fun foo(bar: Int): Unit = when(bar) {
    0 -> println("0")
    else -> eraseReturnValue(printAndReturnTrue(bar))
}

fun eraseReturnValue(value: Any) = Unit

或者我使用完整的函数形式:

fun foo(bar: Int): Unit { 
    when(bar) {
        0 -> println("0")
        else -> printAndReturnTrue(bar)
    }
}

我确信有一些惯用的方法(或者是最后一个例子?),但是现在我找不到它们。

6 个答案:

答案 0 :(得分:7)

不幸的是,没有惯用的方法来做到这一点。一个类似的问题,将(T) -> Boolean类型的lambda传递给接受(T) -> Unit lambdas的函数,之前已经出现了,并且在那里需要进行自动转换应该会在将来某个时候出现。

目前,您可以使用when表达式末尾的扩展功能将其强制转换为Unit值:

fun Any?.toUnit() = Unit

fun foo(bar: Int): Unit = when(bar) {
    0 -> println("0")
    else -> printAndReturnTrue(bar)
}.toUnit()

或者,扩展属性,如果你碰巧更喜欢它:

val Any?.unit get() = Unit

fun foo(bar: Int): Unit = when(bar) {
    0 -> println("0")
    else -> printAndReturnTrue(bar)
}.unit

当然,如果你使用其中任何一个,你可以省略函数的显式Unit返回类型。

答案 1 :(得分:3)

我认为最后一个是最惯用的。虽然您不需要明确的: Unit,但如果未指定返回类型,则它是块形式的默认值,如果您尝试返回其他内容,则会收到错误。

但请注意一个细微的细节:当when用作表达式时,除非编译器能够证明所有情况都得到处理,否则需要else;在块形式中它用作声明"和未处理的案件被忽略。

答案 2 :(得分:1)

作为另一种选择,你可以创建一个更高阶函数,吞下函数的输出,返回一个值:

fun consume (fn: () -> Any): Unit {
  fn()
}

,并提供:

fun foo(bar: Int): Unit = when(bar) {
    0 -> println("0")
    else -> consume { printAndReturnTrue(bar) }
}

答案 3 :(得分:0)

我认为你应该将函数的返回类型更改为可选,它更清楚,如下所示:

def buttonCollide():
   global state
   ...

答案 4 :(得分:0)

如果我在一行中写,我只会使用分号。

someExpression; Unit

答案 5 :(得分:0)

您也可以做类似的事情

fun foo(bar: Int): Unit = when(bar) {
    0 -> println("0")
    else -> printAndReturnTrue(bar).let{ Unit }
}