#boolean #flip #operator #ruby #expressions #perl #macro

flip-flop

此库实现了 Perl 和 Ruby 中的翻转操作符,作为一个 Rust 宏。

1 个稳定版本

1.0.0 2024 年 4 月 1 日

#649Rust 模式

MIT/Apache

8KB
79

flip_flop.rs

此库实现了从 Perl 和 Ruby 中提取的 翻转操作符,作为一个 Rust 宏。

变更日志

  • 2024 年 4 月 1 日:版本 1.0.0。

用法

flip_flop! 接受两个布尔表达式,用括号包裹并使用两个点 (..) 或三个点 (...) 分隔。

flip_flop!((x == 5)..(x == 10))
// or
flip_flop!((x == 5)...(x == 10))

该宏从左表达式为真时返回 true,直到右表达式为真,通过维护一个隐藏的 bool 状态来实现。

..... 之间的区别是,在 ... 中,当左表达式首次变为真时,也会评估右表达式,这使得可以在同一迭代中将翻转内部状态重置。此行为与 Perl 匹配。

操作符的内部状态存储在静态的 AtomicBool 中,因此线程之间共享,类似于 Perl 的行为。

示例

以下代码中的打印语句从 i == 5 变为真时开始执行,直到 i == 10 变为真。

use flip_flop::flip_flop;

fn main() {
    for i in 0..20 {
        // Prints 5, 6, 7, 8, 9, 10.
        if flip_flop!((i == 5)..(i == 10)) {
            println!("{i}")
        }
    }
}

输出

5
6
7
8
9
10

提取序列示例

以下代码提取所有以 1 开始,后跟任何数字,直到找到 2 的序列。

use flip_flop::flip_flop;

fn main() {
    let xs = [0, 1, 2, 0, 0, 1, 0, 2, 0, 0, 0, 0, 2, 2, 2, 0, 1, 1, 2, 0];

    let ys = xs
        .into_iter()
        .filter(|&x| flip_flop!((x == 1)..(x == 2)))
        .collect::<Vec<_>>();

    println!("Original: {:?}", xs);
    println!("Filtered: {:?}", ys);
}

输出

Original: [0, 1, 2, 0, 0, 1, 0, 2, 0, 0, 0, 0, 2, 2, 2, 0, 1, 1, 2, 0]
Filtered: [1, 2, 1, 0, 2, 1, 1, 2]

FizzBuzz 示例

这是使用翻转操作符实现的经典 FizzBuzz 问题。 来源

use flip_flop::flip_flop;

// https://juliansimioni.com/blog/deconstructing-fizz-buzz-with-flip-flops-in-ruby
fn main() {
    let (mut a, mut b, mut c) = (false, false, false);

    for i in 1..=100 {
        #[rustfmt::skip]
        println!(
            "{}\r{}{}",
            i,
            if flip_flop!(({a = !a; a})..({a = !a; a})) { "" } else { "Fizz" },
            if flip_flop!(({b = !b; b})...(!flip_flop!(({c = !c; c})..({c = !c; c})))) { "" } else { "Buzz" },
        );
    }
}

输出(移除后 \r 隐藏的文本)

1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
…

错误

此 crate 的行为应与 Perl 和 Ruby 匹配,但可能存在未正确处理的情况。如果您发现任何错误,请提出问题(或拉取请求)!

许可证

本项目受以下任一许可证的许可:

任由您选择。

无运行时依赖