iter-python

Python generator expressions ([i!]) and "list" comprehensions ([v!])

Repository Latest version Documentation MSRV unsafe forbidden License

Usage

  1. Add the following line to your Cargo.toml, under [dependencies]:

    toml iter-python = "0.10.0"

  2. Bring [i!] and [(enhanced) v!ec][v!] into scope in you Rust code with:

    rust use ::iter_python::prelude::*;

Example

``rust use ::iter_python::prelude::{*, // Not necessary, but sincevsupersedes stdlib'svec`'s API, // you can do this if you feel like it. v as vec, };

fn main () { // i! macro for comprehension "lists" (iterators): let infiniteodds = || i!(2 * n + 1 for n in 0..); let sumsofodds = i!(infiniteodds().take(n).sum() for n in 1..); assert!(sumsofodds.take(100).all(is_square)); /* The above may be suprising, but is an obvious mathematical property once we represent it as:

1> 1   3   5   M-1
       |   |    |
3> 1---2   4   M-#
           |    |
5> 1---2---3   M-n
                |
M> 1---#---n---n+1  where M=2n+1

*/

// `v!` macro: like `vec!`, but supporting `i!`'s input as well.
let v = v![
    2 * x
    for &x_opt in &[None, Some(21), None]
    if let Some(x) = x_opt
];
assert_eq!(
    dbg!(v),
    vec![42],  // `v!` does indeed feature classic `vec!` semantics.
);


// A more advanced example: generate the following string…
const MATRIX: &str = "\

+-----+-----+-----+-----+-----+ | a11 | a12 | a13 | a14 | a15 | | a21 | a22 | a23 | a24 | a25 | | a31 | a32 | a33 | a34 | a35 | | a41 | a42 | a43 | a44 | a45 | | a51 | a52 | a53 | a54 | a55 | +-----+-----+-----+-----+-----+"; const N: usize = 6;

// … using only one allocation!
// This is achieved by combining lazy iterators (`i!`) with
// "lazy strings" / lazy `Display`ables: `lazy_format!`.
use ::iter_python::macros::lazy_format; // prelude provides it as `f!`
let line = || lazy_format!(
    "+-{}-+",
    "-+-".join(i!("---" for _ in 1..N))
);
let top_line = line();
let body = "\n".join(i!(
    lazy_format!(
        "| {} |",
        " | ".join(i!(f!("a{i}{j}") for j in 1..N)),
    )
    for i in 1..N
));
let bottom_line = line();
// Heap-allocation and iterator consumption occurs here:
let matrix = format!("{top_line}\n{body}\n{bottom_line}");
assert_eq!(matrix, MATRIX);

}

fn is_square (n: u32) -> bool { n == ((n as f64).sqrt().trunc() as u32).pow(2) } ```

See [iter!] and [vec!] for more examples.

no_std support

This crates supports #![no_std], by disabling the default "std" feature.