将Kotlin WHEN子句用于<<;=>;=&燃气轮机;比较

将Kotlin WHEN子句用于<<;=>;=&燃气轮机;比较,kotlin,Kotlin,我试图使用带有或0){ doSomethingWhen阳性() } 否则如果(foo0不是有效的表达式,因此不会编译 此外,Kotlin中的范围是封闭的,因此您不能不尝试使用无界范围 相反,您应该使用带有完整表达式的when语句,如示例所示: when { foo > 0 -> doSomethingWhenPositive() foo < 0 -> doSomethingWhenNegative() else -> doSomethingW

我试图使用带有
WHEN
子句。/p pThis无法编译。有没有办法在比较中使用布尔运算符(=,=)的正常集合来启用此功能?/p pYou可以将整个表达式放在第二部分,这是可以的,但似乎是不必要的重复。至少它编译并工作。/p 早熟母鸡{ foo 0-dosomethingwhen阳性() foo 0-doSomethingWhenNegative() else-doSomethingWhenZero() } /编码/预编码 但我不确定这是否比我们多年来一直采用的if-else方法简单。类似于:/p的内容 预编码(foo>0){ doSomethingWhen阳性() } 否则如果(foo<0){ doSomethingWhenNegative() } 否则{ doSomethingWhenZero() }
当然,现实世界中的问题比上述问题更复杂,
WHEN
子句很有吸引力,但并不像我期望的那样适用于这种类型的比较。

即使像Kotlin这样灵活的语言也不能为每种情况提供“优雅的”/“干巴的解决方案”

你可以这样写:

if ( foo > 0 ) {
    doSomethingWhenPositive()
}
else if (foo < 0) {
    doSomethingWhenNegative()
}
else {
    doSomethingWhenZero()
}
when (foo) {
    in 0 .. Int.MAX_VALUE -> doSomethingWhenPositive()
    0    -> doSomethingWhenZero()
    else -> doSomethingWhenNegative()
}
但是,这取决于变量类型

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

when {
    foo > 0  -> doSomethingWhenPositive()
    foo == 0 -> doSomethingWhenZero()
    else     -> doSomethingWhenNegative()
}
嗯。。。有一些(最小的)代码重复

一些语言(Ruby?!)试图为任何情况提供一种超级优雅的形式,但有一个折衷:这种语言变得更加复杂,程序员更难理解端到端

我的2美分…

当条件如下时,

whenCondition (used by whenEntry)
  : expression
  : ("in" | "!in") expression
  : ("is" | "!is") type
  ;
这意味着您只能将
is
in
用作不必是完整表达式的特殊情况;其他一切都必须是正常的表达式。由于
>0
不是有效的表达式,因此不会编译

此外,Kotlin中的范围是封闭的,因此您不能不尝试使用无界范围

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

when {
    foo > 0 -> doSomethingWhenPositive()
    foo < 0 -> doSomethingWhenNegative()
    else -> doSomethingWhenZero()
}
什么时候{
foo>0->doSomethingWhenPositive()
foo<0->doSomethingWhenNegative()
else->doSomethingWhenZero()
}
或者:

when {
    foo < 0 -> doSomethingWhenNegative()
    foo == 0 -> doSomethingWhenZero()        
    foo > 0 -> doSomethingWhenPositive()        
}
什么时候{
foo<0->doSomethingWhenNegative()
foo==0->doSomethingWhenZero()
foo>0->doSomethingWhenPositive()
}

这可能更具可读性。

您希望您的代码更加优雅,那么为什么在使用
表达式时仍使用
。Kotlin足够灵活,可以使用扩展构建一个新的

首先,我们应该声明,我们只能在此处传递一个
可比较的
,因为您必须比较该值

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

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
}

如果您满意,可以将
减号
函数重命名为
compareTo
并返回0。通过这种方式,您可以将
-
替换为
=>
,它看起来像scala。

我发现了一种有点老套的方法,可以帮助您将大于、小于或任何其他表达式与其他In表达式混合。 简单地说,Kotlin中的when语句查看“case”,如果它是一个范围,它会查看变量是否在该范围内,如果不在该范围内,它会查看case是否与变量的类型相同,如果不是,则会出现语法错误。所以,为了解决这个问题,你可以这样做:

when (foo) {
    if(foo > 0) foo else 5 /*or any other out-of-range value*/ -> doSomethingWhenPositive()
    in -10000..0   -> doSomethingWhenBetweenNegativeTenKAndZero()
    if(foo < -10000) foo else -11000 -> doSomethingWhenNegative()
}
when(foo){
如果(foo>0)foo else 5/*或任何其他超出范围的值*/->doSomethingWhen正值()
在-10000..0->零和零之间的dosomething()
if(foo<-10000)foo else-11000->doSomethingWhenNegative()
}

如您所见,这充分利用了Kotlin中的所有内容都是表达式这一事实。因此,依我看,这是一个非常好的解决方案,直到这个特性被添加到语言中。

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

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

希望这有帮助

看看语法很有趣。因此,第一个
表达式
看起来需要是一个返回布尔值的表达式,这就是我在编译的示例中使用的。是这样吗。带有“in”子句的第二个表达式是返回某种集合的表达式,“is”只是一个类型声明。对吗?不管怎么说,我猜每种情况下的完整表达式是这里最干净的选项。这是一个有用的例子,说明了如何做一些比我需要的更复杂的事情。我计划只使用标准WHEN子句,但可能希望参考此示例了解更多类似性质的内容。这样的框架是可伸缩的,您可以通过多种方式对其进行扩展,例如模式匹配。这实际上并不比原始的
WHEN{foo>0->…;foo<0->;else->…]更具可读性,也不比原始的
更出色
。我知道,但如果您无论如何都必须使用它,它仍然是一个不错的选择。您还可以创建一个外部函数来执行此操作,以使其更具可读性
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
}
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.
}
when (foo) {
    if(foo > 0) foo else 5 /*or any other out-of-range value*/ -> doSomethingWhenPositive()
    in -10000..0   -> doSomethingWhenBetweenNegativeTenKAndZero()
    if(foo < -10000) foo else -11000 -> doSomethingWhenNegative()
}
response.code().let {
    when {
        it == 200 -> handleSuccess()
        it == 401 -> handleUnauthorisedError()
        it >= 500 -> handleInternalServerError()
        else -> handleOtherErrors()
    }
}