lup 0.2.0

A custom indexed loop macro library for Rust.
Documentation
# Lup ("loop")

A custom indexed loop macro library for Rust.

This library offers a different pattern than iterators based on indexed loops.
Index loops are very common in game programming and scientific computing.
The loops included in the library reflects the ones used in [Dyon](https://github.com/pistondevelopers/dyon).

You can create your own custom loops by implementing the `Lup` trait.

### Motivation

- Closer to mathematical notation than the iterator pattern
- Reduces chance of logical errors when solving complex problems
- Supports `continue`, `break` or `return` from within the loop
- Packed notation for nested loops, `i in 0..3, j in 0..3 =>`
- Short-hand notation with safe range, `i, j by list =>`
- Automatically infers evidence type of secrets
- Can be used for numeric brute-force theorem proving
- Ergononmic when working with vectors up to 4 dimensions

### Usage

The loops `Any`, `All`, `Max` and `Min` uses the `Secret` structure.
This type contains evidence that justifies the value.

Here is a simple example using the `Any` loop and the `by` syntax:

```rust
#[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`.
}
```

The `by` syntax uses the range from the list.
In the example above, this is the same as:

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

Here is a slightly more complex example:

```rust
#[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`.
}
```

In the example above, there are two loops, one with index `i` and one with index `j`.

The type of the result of the inner `j` loop is `Secret<(usize), bool>`.

The type of the result of the outer `i` loop is `Secret<(usize, usize), bool>`.

The `Secret` type is used to combine results from loops to give meaningful answers.

Another example using the `Max` loop:

```rust
#[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)`.
}
```

We convert to `f32` since `Max` is implemented only for `f32` and `f64`.

The evidence points to the item that first achieves maximum value.

Here is an example that demonstrates the full power of secrets:

```rust
#[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`.
}
```

How do we know that a list has a maximum value less than 7?
We know it because the maximum value of the first list is 6!

Secrets provide us with a meaningful reason why something is true.

In the example above, the secret of the `Max` loop propagates to the `Any` loop.

The example calls `.le` instead of using `<=` because Rust does not allow
overriding the return value of comparison operators.