使用Kotlin WHEN子句进行<,<=,> =,>比较

Jim*_*ask 24 kotlin

我正在尝试将该WHEN子句用于>或<比较.

这不编译.有没有办法在比较中使用正常的布尔运算符集(<=,> =>)来启用它?

val foo = 2

// doesn't compile
when (foo) {
    > 0 -> doSomethingWhenPositive()
    0   -> doSomethingWhenZero()
    < 0 -> doSomethingWhenNegative()
}
Run Code Online (Sandbox Code Playgroud)

我试图找到一个无限范围比较,但也无法使这项工作?是否可以将其写为无界范围?

// trying to get an unbounded range - doesn't compile
when (foo) {
    in 1.. -> doSomethingWhenPositive()
    else -> doSomethingElse()
}
Run Code Online (Sandbox Code Playgroud)

你可以将整个表达式放在第二部分,这是好的,但似乎是不必要的重复.至少它编译和工作.

when {
    foo > 0 -> doSomethingWhenPositive()
    foo < 0 -> doSomethingWhenNegative()
    else -> doSomethingWhenZero()
}
Run Code Online (Sandbox Code Playgroud)

但我不确定这比我们多年来一直在做的if-else替代方案更简单.就像是:

if ( foo > 0 ) {
    doSomethingWhenPositive()
}
else if (foo < 0) {
    doSomethingWhenNegative()
}
else {
    doSomethingWhenZero()
}
Run Code Online (Sandbox Code Playgroud)

当然,现实问题比上述问题更复杂,并且该WHEN条款具有吸引力,但不能像我期望的那样进行这种比较.

Lio*_*-On 20

即使是像Kotlin这样的灵活语言也没有针对每个案例的"优雅"/ DRY解决方案.

你可以这样写:

when (foo) {
    in 0 .. Int.MAX_VALUE -> doSomethingWhenPositive()
    0    -> doSomethingWhenZero()
    else -> doSomethingWhenNegative()
}
Run Code Online (Sandbox Code Playgroud)

但是你依赖于变量类型.

我认为以下形式是Kotlin中最惯用的形式:

when {
    foo > 0  -> doSomethingWhenPositive()
    foo == 0 -> doSomethingWhenZero()
    else     -> doSomethingWhenNegative()
}
Run Code Online (Sandbox Code Playgroud)

是的......有一些(最小的)代码重复.

有些语言(Ruby ?!)试图为任何情况提供一种超级优雅的形式 - 但有一个权衡:语言变得更复杂,更难以让程序员知道端到端.

我的2美分......

  • 我相信 `in 0 .. Int.MAX_VALUE -&gt; {}` 会翻译为 `foo &gt;= 0 &amp;&amp; foo &lt;= Int.MAX_VALUE`,其中在 when 子句的第一部分中包含 0 (2认同)

Pix*_*ant 8

该语法用于when条件如下:

whenCondition (used by whenEntry)
  : expression
  : ("in" | "!in") expression
  : ("is" | "!is") type
  ;
Run Code Online (Sandbox Code Playgroud)

这意味着您只能使用is或in不必是完整表达式的特殊情况。其他所有内容都必须是正则表达式。由于> 0不是有效的表达式,因此无法编译。

此外,范围在Kotlin中是封闭的,因此您无法逃避尝试使用无界范围。

相反,您应该使用when带有完整表达式的语句,如您的示例所示:

when {
    foo > 0 -> doSomethingWhenPositive()
    foo < 0 -> doSomethingWhenNegative()
    else -> doSomethingWhenZero()
}
Run Code Online (Sandbox Code Playgroud)

或者:

when {
    foo < 0 -> doSomethingWhenNegative()
    foo == 0 -> doSomethingWhenZero()        
    foo > 0 -> doSomethingWhenPositive()        
}
Run Code Online (Sandbox Code Playgroud)

可能更具可读性。


ice*_*000 6

您希望您的代码优雅,那么为什么要停留在when表达式上。Kotlin 足够灵活,可以使用扩展来构建一个新的。

首先,我们应该声明我们只能在Comparable<T>此处传递 a因为您必须比较该值。

然后,我们有了我们的框架:

fun <T: Comparable<T>> case(target: T, tester: Tester<T>.() -> Unit) {
    val test = Tester(target)
    test.tester()
    test.funFiltered?.invoke() ?: return
}
class Tester<T : Comparable<T>>(val it: T) {
    var funFiltered: (() -> Unit)? = null
    infix operator fun Boolean.minus(block: () -> Unit) {
        if (this && funFiltered == null) funFiltered = block
    }

    fun lt(arg: T) = it < arg
    fun gt(arg: T) = it > arg
    fun ge(arg: T) = it >= arg
    fun le(arg: T) = it <= arg
    fun eq(arg: T) = it == arg
    fun ne(arg: T) = it != arg
    fun inside(arg: Collection<T>) = it in arg
    fun inside(arg: String) = it as String in arg
    fun outside(arg: Collection<T>) = it !in arg
    fun outside(arg: String) = it as String !in arg
}
Run Code Online (Sandbox Code Playgroud)

之后,我们可以有优雅的代码,如:

case("g") {
    (it is String) - { println("hello") } // normal comparison, like `is`
    outside("gg") - { println("gg again") } // invoking the contains method
}

case(233) {
    lt(500) - { println("less than 500!") }
    // etc.
}
Run Code Online (Sandbox Code Playgroud)

如果你感到快乐,你可以重命名minus功能,compareTo并返回0。以这样的方式,可以更换-用=>,它看起来像斯卡拉。


Nav*_*T P 6

我们可以使用let来实现这种行为。

response.code().let {
    when {
        it == 200 -> handleSuccess()
        it == 401 -> handleUnauthorisedError()
        it >= 500 -> handleInternalServerError()
        else -> handleOtherErrors()
    }
}
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助

  • 在新版本的 kotlin 中,你可以执行 `when (val code = response.code()) { code == 200 -&gt; ... }` (4认同)