12 个版本 (6 个重大更新)
0.7.0 | 2024 年 7 月 29 日 |
---|---|
0.6.2 | 2024 年 3 月 20 日 |
0.5.3 | 2022 年 11 月 26 日 |
0.5.1 | 2021 年 3 月 7 日 |
0.4.2 | 2020 年 7 月 21 日 |
在 Rust 模式 中排名第 217
每月下载量 780 次
在 4 个 crate 中使用(3 个直接使用)
36KB
260 行
bool_ext
一个定义并实现了一整套布尔函数式组合子的 crate。
常见问题解答
不是已经有类似的 crate 了吗?
是的,已经有一些了,比如 Daniel Keep 的 boolinator,以及 Rust 的 then()
和 then_some()
方法。
boolinator
是一个很棒的 crate,也是这个 crate 的灵感来源之一,还有一些其他来源。然而,boolinator
提供的组合子集合并不像人们希望的那样完整(相对较小的细节是,组合子的名字也没有尽可能简短。 boolinator
的接口也是稳定的(即 >v1.0.0),这将是一个破坏性的更新。)
Rust 的情况是,由于设计保守,std
将非常缓慢地向完整的组合子集合发展。
我希望这个 crate 可以作为布尔组合子的命名和范围的测试平台,以帮助 Rust 语言团队根据使用数据和反馈进行讨论和决策。
这只是一个布尔值--为什么 API 表面如此庞大?
嗯,因为 bool
是一个非常灵活的数据类型!例如,只有当问题中的项目尚未存在于集合中时才添加,这是一种常见的操作。《code>Map 数据类型通常通过其设计特性提供这种行为。其他容器如 Vec
则不是。因此,我们不需要高度状态化的命令式代码
// ...
let mut found = false;
for needle in haystack {
if needle == item {
found = true;
break;
}
}
if !found {
haystack.push(item);
}
或命令式/声明式混合代码
// ...
if !haystack.contains(&item) {
haystack.push(item)
}
bool_ext
使以下高度表达、高度凝聚的声明式代码成为可能
// ...
haystack.contains(&item)
.or_do(|| haystack.push(item));
我应该使用这个吗?/我对方法链/函数组合子不太确定
你不是一个人!调试器还没有跟上流畅API设计技术的步伐,调试流畅接口确实可能需要更多的工作。另一方面,支持者(如我)会告诉你,通过将思维从“微观管理CPU”提升到通过“塑造数据”来表达意图,从一开始就能编写出更少的错误,生成的代码将更加具有表现力和易于维护(一旦维护者积累了足够的这种编码风格的经验)。
bool_ext
的实现遵循 Bjarne Stroustrup 对零开销抽象的经典定义,即 1) 你只为使用的部分付费,2) 即使你自己手动编写代码,也无法更好地实现这个抽象。
关于 1),bool_ext
创建的非常小,不依赖任何外部库,最重要的是,你未使用的任何方法都会被编译器移除,并且不会成为你生成的二进制文件的一部分。
关于 2),每个方法都是 #[inline]
,遵循单一责任原则,最小化内联产生的寄存器压力,并且在完全优化(通常在发布模式下)后应该编译成与手动编写相同的(或更好的)代码。
那么,如何取反一个布尔值呢?
直到 v0.4.0,bool_ext
几乎为每个方法都包含一个 _false
变体。感谢 izik1 的反馈以及大量的考虑,我决定使用 boolean_condition
.not.ok 而不是 boolean_condition
.ok_false 或 boolean_condition
.or_ok。我发现 (!boolean_condition
()).ok 读写性差得多(因为需要括号,并且操作顺序不再完全是左到右),但正如 izik1 指出的,std::ops::Not
缓解了这个问题。谢谢,izik1! :)
许可证
根据您的选择,许可如下。
* MIT license (see LICENSE-MIT file)
* Apache License, Version 2.0 (see LICENSE-APACHE file)
。
贡献
除非您明确声明,否则您提交的任何旨在包含在作品中的贡献,都将根据上述方式双许可,不附加任何额外的条款或条件。