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

我试图使用WHEN子句与><比较。

这不会编译。 在比较中使用普通的布尔运算符(<= =,> =>)来实现这一点吗?

 val foo = 2 // doesn't compile when (foo) { > 0 -> doSomethingWhenPositive() 0 -> doSomethingWhenZero() < 0 -> doSomethingWhenNegative() } 

我试图找到一个无界的范围比较,但无法做到这一点呢? 有可能把这个写成一个无限的范围吗?

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

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

 when { foo > 0 -> doSomethingWhenPositive() foo < 0 -> doSomethingWhenNegative() else -> doSomethingWhenZero() } 

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

 if ( foo > 0 ) { doSomethingWhenPositive() } else if (foo < 0) { doSomethingWhenNegative() } else { doSomethingWhenZero() } 

当然,现实世界的问题比上面的要复杂得多,而WHEN子句是有吸引力的,但是并不像我预期的那样。

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

你可以写下如下的东西:

 when (foo) { in 0 .. Int.MAX_VALUE -> doSomethingWhenPositive() 0 -> doSomethingWhenZero() else -> doSomethingWhenNegative() } 

但是你依赖于变量类型。

我相信以下的形式是Kotlin最习惯的:

 when { foo > 0 -> doSomethingWhenPositive() foo == 0 -> doSomethingWhenZero() else -> doSomethingWhenNegative() } 

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

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

我的2分钱…

when条件的语法如下:

 whenCondition (used by whenEntry) : expression : ("in" | "!in") expression : ("is" | "!is") type ; 

这意味着你只能使用isin作为特殊情况,而不必是一个完整的表达式; 一切都必须是一个正常的表达。 由于> 0不是一个有效的表达式,所以不能编译。

而且,范围在Kotlin中是封闭的,所以你不能逃避尝试使用无限范围。

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

 when { foo > 0 -> doSomethingWhenPositive() foo < 0 -> doSomethingWhenNegative() else -> doSomethingWhenZero() } 

或者:

 when { foo < 0 -> doSomethingWhenNegative() foo == 0 -> doSomethingWhenZero() foo > 0 -> doSomethingWhenPositive() } 

这可能更具可读性。

你想要你的代码优雅,所以为什么留在表达式。 Kotlin足够灵活,可以使用扩展来创建一个新的。

首先,我们应该声明我们只能传递一个Comparable<T> ,因为你必须比较这个值。

那么,我们有我们的框架:

 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. } 

如果你感到高兴,你可以重命名minus函数compareTo并返回0.这样,你可以用- =>替换- => ,看起来像scala。