#combinator #boolean #bool #functional #adapter

no-std bool_ext

一个 crate,它定义并实现了 Rust 原生类型 bool 上的一整套类似于 OptionResult 的布尔函数式组合子。

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

Download history 106/week @ 2024-05-04 166/week @ 2024-05-11 202/week @ 2024-05-18 123/week @ 2024-05-25 214/week @ 2024-06-01 89/week @ 2024-06-08 103/week @ 2024-06-15 96/week @ 2024-06-22 48/week @ 2024-06-29 138/week @ 2024-07-06 126/week @ 2024-07-13 84/week @ 2024-07-20 254/week @ 2024-07-27 291/week @ 2024-08-03 160/week @ 2024-08-10 64/week @ 2024-08-17

每月下载量 780
4 crate 中使用(3 个直接使用)

MIT/Apache

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_falseboolean_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)

贡献

除非您明确声明,否则您提交的任何旨在包含在作品中的贡献,都将根据上述方式双许可,不附加任何额外的条款或条件。

无运行时依赖