将Kotlin WHEN子句用于<<;=>;=&燃气轮机;比较
我试图使用带有将Kotlin WHEN子句用于<<;=>;=&燃气轮机;比较,kotlin,Kotlin,我试图使用带有或0){ doSomethingWhen阳性() } 否则如果(foo0不是有效的表达式,因此不会编译 此外,Kotlin中的范围是封闭的,因此您不能不尝试使用无界范围 相反,您应该使用带有完整表达式的when语句,如示例所示: when { foo > 0 -> doSomethingWhenPositive() foo < 0 -> doSomethingWhenNegative() else -> doSomethingW
或子句。/p pThis无法编译。有没有办法在比较中使用布尔运算符(=,=)的正常集合来启用此功能?/p pYou可以将整个表达式放在第二部分,这是可以的,但似乎是不必要的重复。至少它编译并工作。/p 早熟母鸡{ foo 0-dosomethingwhen阳性() foo 0-doSomethingWhenNegative() else-doSomethingWhenZero() } /编码/预编码 但我不确定这是否比我们多年来一直采用的if-else方法简单。类似于:/p的内容 预编码(foo>0){ doSomethingWhen阳性() } 否则如果(foo<0){ doSomethingWhenNegative() } 否则{ doSomethingWhenZero() }WHEN
当然,现实世界中的问题比上述问题更复杂,
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()
}
}