Kotlin中如何避免中缀函数调用时左侧表达式的括号?
解决Kotlin中缀函数省略比较表达式括号的问题
这个问题其实是Kotlin运算符优先级规则在搞鬼!你定义的then是中缀函数,而Kotlin里中缀函数调用的优先级高于比较运算符(>、<等)。所以当你写index > 0 then { data[index - 1].id }时,编译器会错误地解析成:
index > (0 then { data[index - 1].id })
显然0是Int类型,没有then扩展函数,所以会报编译错误。
下面给你几个可行的解决办法:
1. 退而求其次:保留括号(最直接的方案)
虽然你不想加,但这是最符合Kotlin语法规范的写法,完全没有歧义:
(index > 0) then { data[index - 1].id }
2. 定义比较相关的中缀函数(实现无括号的中缀链式调用)
把比较运算也改成中缀函数调用,这样整个表达式都是同优先级的中缀调用,Kotlin会按左结合的规则解析,自然不需要括号。比如先定义几个比较用的中缀扩展:
infix fun Int.gt(other: Int): Boolean = this > other infix fun Int.lt(other: Int): Boolean = this < other infix fun Int.ge(other: Int): Boolean = this >= other infix fun Int.le(other: Int): Boolean = this <= other infix fun Int.eq(other: Int): Boolean = this == other
之后你就可以这样写:
index gt 0 then { data[index - 1].id }
这个写法完全符合你的需求,没有括号,可读性也不错。
3. 用标准库函数替代(无需自定义中缀)
如果你不想额外定义比较中缀函数,可以用Kotlin标准库的takeIf结合run/let来实现类似逻辑,虽然不是中缀写法,但也不需要括号:
index.takeIf { it > 0 }?.run { data[this - 1].id }
takeIf会在条件满足时返回自身,否则返回null,之后用?.安全调用run,在run的lambda里this就是满足条件的index,逻辑和你的then函数完全一致。
内容的提问来源于stack exchange,提问作者Elchin Heybatov
相关产品推荐
相关产品推荐

