为什么 Kotlin 中没有 ClosedRange IN ClosedRange 运算符?

Why is there no ClosedRange IN ClosedRange Operator in Kotlin?

val a, b, x, y: LocalDate.

那么 a..b in x..y 不是有效的表达式:ClosedRange in ClosedRange 未定义。

但是,(a..b).toRange() in (x..y).toRange() 确实有效,因为 Range in Range 已定义。

除了 b < ay < x 因为 ranges 不能为负数。

请注意,我正在为 Android 开发,这是 .toRange() 的来源:androidx.core/core-ktx


3个问题出现

免责声明:我不是 Android 开发人员,也没有使用 androidx.core 的经验,所以请对我的回答持保留态度。

所以假设你可以 a..b 创建一个 ClosedRange(这在 Kotlin stdlib 中默认不可用,但也许 core-ktx 定义了它自己的扩展),根据 Kotlin documentation, x in y gets translated to y.contains(x). Now, ClosedRange 定义了一些 contains 方法,但其中 none 接受另一个 ClosedRange 作为参数,因此你的错误。

现在,显然 Android stdlib 定义了它自己的 Range, which is unrelated to Kotlin's ClosedRange (as one does not extend the other). However, core-ktx defines a function to transform a ClosedRange to a Range, and that function is .toRange(). In addition to that, Range defines a contains(Range) 方法概念,这就是第二个示例编译正确的原因。

总结一下:Kotlin 不允许 (1) 默认创建日期范围,以及 (2) 检查一个范围是否完全包含在另一个范围内。但是,您可以轻松克服 (1) 通过创建自己的函数来为日期创建 ClosedRange(通过创建 rangeTo extension function),以及 (2) 通过创建自己的 contains(Range) 函数。


回到为什么 a..b 在使用 core-ktx 时有效,我找不到满意的答案。该库包含一个 rangeTo 扩展函数,用于创建任何 Comparable 范围之外的范围(并且 LocalDate 是一个 Comparable),但是该函数 returns Range,而不是 ClosedRange,所以我不确定为什么 a..b in x..y 首先不起作用。

ClosedRange 是 Kotlin 标准库的一部分。范围是 Android 的 SDK 的一部分。这两个库是由不同的公司制作的,并且在制作时考虑到了不同的目标,因此您不一定可以将其称为疏忽。也许 Kotlin 开发人员认为一个范围在另一个范围内的含义可能不明确,而 Android 开发人员则没有。或者,也许 Kotlin 开发人员对哪些功能足够有用以包含在标准库中有更高的标准。

两个 classes 之间的一个区别是 Android Range class 禁止起始值高于较低值的范围,但 Kotlin ClosedRange 允许。这使得包含另一个 ClosedRange 的概念比 Ranges 更加模糊。负方向 ClosedRange 位于另一个 ClosedRange 中意味着什么?它是空的,但它有一个跨度。

我不确定你所说的绕过它是什么意思。如果需要,您可以为 ClosedRange 定义自己的扩展函数,其行为取决于您希望如何解释包含的空范围的含义。

operator fun <T: Comparable<T>> ClosedRange<in T>.contains(other: ClosedRange<out T>): Boolean =
    other.start in this && other.endInclusive in this

// or

operator fun <T: Comparable<T>> ClosedRange<in T>.contains(other: ClosedRange<out T>): Boolean =
    other.isEmpty() || (other.start in this && other.endInclusive in this)

// or

operator fun <T: Comparable<T>> ClosedRange<in T>.contains(other: ClosedRange<out T>): Boolean =
    (other.isEmpty() && (other.start in this || other.endInclusive in this)) || 
        (other.start in this && other.endInclusive in this)