3个版本 (破坏性更新)

使用旧的Rust 2015

0.3.0 2018年5月24日
0.2.0 2018年5月24日
0.1.0 2018年5月6日

#2060游戏开发

MIT 许可证

34KB
594

卢普 ("循环")

为Rust提供的自定义索引循环宏库。

此库提供了一种基于索引循环的迭代器模式之外的不同模式。索引循环在游戏编程和科学计算中非常常见。库中包含的循环反映了在Dyon中使用的循环。

您可以通过实现Lup特质来创建自己的自定义循环。

动机

  • 比迭代器模式更接近数学符号
  • 在解决复杂问题时,减少了逻辑错误的机会
  • 支持在循环内使用continuebreakreturn
  • 嵌套循环的紧凑表示法,i in 0..3, j in 0..3 =>
  • 带有安全范围的缩写表示法,i, j by list =>
  • 自动推断秘密的证据类型
  • 可用于数值暴力定理证明
  • 当与最多4维度的向量一起工作时,更符合人体工程学

用法

循环AnyAllMaxMin使用Secret结构。此类型包含证明值的证据。

以下是一个使用Any循环和by语法的简单示例

#[macro_use]
extern crate lup;

use lup::Any;

fn main() {
    let words = vec!["mary", "had", "a", "little", "lamb"];
    println!("Words:");
    println!("{:?}\n", words);

    // Find the word "lamb".
    let lamb = lup!(Any<_>: i by words => {words[i] == "lamb"});
    println!("Is there any word `lamb`?");
    println!("{}\n", lamb.value); // Prints `true`.

    println!("What is the evidence?");
    println!("{:?}\n", lamb.evidence); // Prints `Some(4)`.

    println!("Using the evidence to find the word:");
    println!("{}\n", words[lamb.evidence.unwrap()]); // Prints `lamb`.
}

by语法使用列表的范围。在上面的例子中,这等同于

lup!(Any<_>: i in 0..words.len() => {words[i] == "lamb"})

以下是一个稍微复杂一些的例子

#[macro_use]
extern crate lup;

use lup::Any;

fn main() {
    // Create a 2D array.
    let arr = [[1, 2], [3, 4]];

    // Look for a number greater than 2.
    let b = lup!(Any<_>: i, j by arr => {arr[i][j] > 2});

    println!("{:?}", b.evidence); // Prints `Some((1, 0))`.

    // Get the number that is greater than 2.
    let ev = b.evidence.unwrap();
    println!("{}", arr[ev.0][ev.1]); // Prints `3`.
}

在上面的例子中,有两个循环,一个索引为i,一个索引为j

内部循环j的结果类型为Secret<(usize), bool>

外层循环 i 的结果是 Secret<<(usize, usize), bool> 类型。

使用 Secret 类型可以将循环的结果组合起来,以给出有意义的答案。

使用 Max 循环的另一个示例

#[macro_use]
extern crate lup;

use lup::Max;

fn main() {
    let data = vec![
        (1, 1),
        (2, 2),
        (3, 4),
        (4, 4)
    ];

    let a = lup!(Max<_, _>: i by data => {data[i].0 as f32});
    let b = lup!(Max<_, _>: i by data => {data[i].1 as f32});

    println!("{} vs {}", a.value, b.value); // Prints `4 vs 4`.
    println!("{:?} vs {:?}", a.evidence, b.evidence); // Prints `Some(3) vs Some(2)`.
}

由于 Max 仅对 f32f64 实现,我们将数据转换为 f32

证据指向第一个达到最大值的项。

以下是一个演示秘密强大功能的示例

#[macro_use]
extern crate lup;

use lup::{Any, Max};

fn main() {
    let data = vec![
        vec![1, 2, 6, 4, 5, 3],
        vec![4, 6, 9, 3, 2, 1],
    ];

    // Find out whether any list has a maximum value less than 7.
    let search = lup!(Any<_>: i by data => {
        lup!(Max<_, _>: j by data[i] => {data[i][j] as f32}).le(&7.0)
    });

    println!("{}", search.value); // Prints `true`.
    println!("{:?}", search.evidence); // Prints `Some((0, 2))`.
    let ev = search.evidence.unwrap();
    println!("{}", data[ev.0][ev.1]); // Prints `6`.
}

我们如何知道一个列表的最大值小于7?我们知道,因为第一个列表的最大值是6!

秘密为我们提供了为什么某事为真的有意义的理由。

在上面的示例中,Max 循环的秘密传播到 Any 循环。

示例调用 .le 而不是使用 <=,因为 Rust 不允许覆盖比较运算符的返回值。

无运行时依赖