#range #numbers #spans #interval #replace

extent

std::ops::{Range,RangeInclusive} 的替代品

5 个版本 (破坏性更新)

0.5.0 2022年12月17日
0.4.0 2022年12月17日
0.3.0 2022年5月22日
0.2.0 2022年1月1日
0.1.0 2022年1月1日

#22 in #number

MIT/Apache

18KB
309 行代码(不含注释)

extent

这是 std::ops::{Range,RangeInclusive} 的一个替代品,避免了这些类型的一些特性(非 Copy,无法在不使用额外的 bool 的情况下产生空范围,直接实现 Iterator 等)。请参阅 https://ridiculousfish.com/blog/posts/least-favorite-rust-type.htmlhttps://kaylynn.gay/blog/post/rust_ranges_and_suffering 以了解其罪行清单。

今天我恰好在我自己的一个 crate 中编写这个类型时看到了第二篇文章,所以我决定将其拆分出来,并作为一个 crate 发布供其他人使用。它有一些特性和限制,但比我使用的内置类型更符合我的需求。以下是我的选择:

  1. Extent 表示一个包含数字的范围,其中数字是来自(相当标准的)num-traits crate 的 N:PrimInt。它是包含的,因为(至少是最明显的)排除范围无法表示数字类型的最大值,在我的经验中,这通常是需要表示的!

  2. Extent 使用 exactly 2 个数字和没有额外的标志或浪费的空间。

  3. Extent 可以表示空范围。空范围以 {lo=1, hi=0} 的规范化形式表示。这是唯一的这种情况,其中 lo > hi,并且只能通过静态函数 empty 或 IO 方向的函数 new_unchecked 来构造。端点的典型访问器 lo()hi() 返回一个 Option<N>,在空的情况下返回 None。如果您想得到原始形式(例如,用于 IO),可以调用 lo_unchecked()hi_unchecked(),这些函数被标记为 unsafe,因为它们不反映重要的 lo <= hi 不变式。

  4. 所有非空情况都在 new 中强制执行 lo <= hi。如果你向 new 传递 hi > lo,则值将被交换(即你可以从点的任意顺序构造;它们将被存储在顺序中)。如果你从原始 IO 值构建,可以使用 new_unchecked,它不会交换,只会将无序范围规范化为 empty(),但也是不安全的。

  5. Extent 实现了 Copy(以及所有其他标准功能)。

  6. Extent 没有实现 Iterator,但它有一个 iter 方法,该方法将 Extent 复制到 ExtentIter,它实现了 Iterator

  7. 还有一个 ExtentRevIter 用于递减计数。

  8. 提供了一些基本的集合运算符(并集、交集、包含),但并没有太多花哨的功能。

欢迎提交补丁来丰富这一点,尽管我会尽量保持它相对简单,并专注于数字范围的用例,而不是“任意事物范围”。

许可证:MIT OR Apache-2.0

依赖项

~155KB