Macro for Python-esque comprehensions in Rust

Related tags

Utilities cute
Overview

Cute

Build Status Build status Crates.io docs.rs License: MIT

Macro for Python-esque list comprehensions in Rust.

The c! macro implements list and hashmap comprehensions similar to those found in Python, allowing for conditionals and nested comprehensions.

Python Syntax

squares = [x*x for x in range(10)]

even_squares = [x*x for x in range(10) if x % 2 == 0]

squares_dict = {key:key*key for key in range(10)}

c! Syntax

let squares = c![x*x, for x in 0..10];

let even_squares = c![x*x, for x in 0..10, if x % 2 == 0];

let squares_hashmap = c!{key => key*key, for key in 0..10};

Note c!'s has the comprehension's parts, comma-separated.

Examples

Simpe comprehension

#[macro_use(c)]
extern crate cute;

let v = [1,2,3,4];
let v_squared = c![x*x, for x in v];

Conditional filtering

let squares = c![x*x, for x in 0..10, if x % 2 == 0];
assert_eq!(squares, vec![0, 4, 16, 36, 64]);

Nested Comprehensions

let nested = vec![vec![1,2,3], vec![4,5,6], vec![7,8,9]];
let flat: Vec<usize> = c![x, for x in y, for y in nested];
assert_eq!(flat, vec![1, 2, 3, 4, 5, 6, 7, 8, 9]);
let nested = vec![vec![1,2,3], vec![4,5,6], vec![7,8,9]];
let even_flat: Vec<usize> = c![x, for x in y, for y in nested, if x % 2 == 0];
assert_eq!(even_flat, vec![2, 4, 6, 8]);

Comprehensions over Iterators

let vec: Vec<i32> = vec![-4, -2, 0, 2, 4];
let output: Vec<i32> = c![x*2, for x in vec.iter()];
assert_eq!(output, vec![-8, -4, 0, 4, 8]);
let vec: Vec<i32> = vec![-4, -2, 0, 2, 4];
let output: Vec<i32> = c![x, for x in vec.iter(), if *x >= 0i32];
assert_eq!(output, vec![0, 2, 4]);

Function Application

let vec: Vec<i32> = vec![-4, -2, 0, 2, 4];
let output: Vec<i32> = c![x.abs(), for x in vec.iter()];
assert_eq!(output, vec![4, 2, 0, 2, 4]);
fn square(x:i32) -> i32 {
       x*x
}
      
let vec: Vec<i32> = vec![-4, -2, 0, 2, 4];
let squares: Vec<i32> = c![square(x), for x in vec];
assert_eq!(squares, vec![16, 4, 0, 4, 16]);

HashMap Comprehensions (Dictionary Comprehensions)

// simple hashmap comprehension

let squares_hashmap = c!{key => key*key, for key in 0..10};
// hashmap comprehension from an Iterator
// NOTE: we have to perform dereferencing: *key

let map = c!{*key => key*key, for key in vec![1,2].iter()};
// conditional hashmap comprehension

let v: Vec<(&str, i32)> = vec![("one", 1), ("two", 2), ("three", 3)];
let map = c!{key => val, for (key, val) in v, if val == 1 || val == 2};

let mut expected: HashMap<&str, i32> = HashMap::new();
expected.insert("one", 1);
expected.insert("two", 2);

assert_eq!(map, expected);
// conditional hashmap comprehension from an Iterator
// NOTE: we perform deferencing when using values

let map = c!{*key => key*key, for key in vec![1,2].iter(), if *key % 2 == 0};
let mut e: HashMap<i32, i32> = HashMap::new();
e.insert(2, 4);

assert_eq!(map, e);
Comments
  • feat: generalized macro rules for repeated patterns

    feat: generalized macro rules for repeated patterns

    Use of one macro rule with extra TT munching recursive macro.

    At every invocation, it processes (munches) only a portion of the input, generates intermediate output, and sends the remaining "unmunched" input tail to another macro invocation. Eventually, the input is small enough to not require any more macro invocations and reaches the base case at which the recursion is terminated.

    This macro rule should work for an arbitrary number of for $i in $iter expressions as long as it stays within the macro recursion limit.

    This address the for part of #7

    opened by mattgathu 0
  • Fix doc tests so they pass. Shouldn't change look of documentation

    Fix doc tests so they pass. Shouldn't change look of documentation

    Hi, I pulled the repo down and I ran the tests. I noticed the doc tests didn't compile, so I fixed them. This shouldn't change the documentation much at all.

    opened by kylegalloway 0
  • Support for variadic

    Support for variadic "for" and "if" statements

    Consider supporting an arbitrary number of for expressions rather than requiring the macro to be extended for each one? This would likely resolve #4, and lead to a fix for #6, and maybe support any number of if expressions as well? A "0-or-more" style of logic would work well, and fit nicely into a recursive macro.

    opened by lynlevenick 0
  • Support for conditionals at any level of looping

    Support for conditionals at any level of looping

    It would be nice to be able to write a conditional at any location in the expression, e.g. c![a + b, for a in some_vec, if a % 5 < 2, for b in 0..10]. This could work well with generators (#1) to reduce nested computations, though I'm not sure how well that would end up vectorizing if at all.

    opened by lynlevenick 0
  • Inconsistent ordering for

    Inconsistent ordering for "for" expressions

    The arity c! is called with determines the iteration order - c![(a, b, c), for a in 0..5, for b in 0..5, for c in 0..5] is iterated differently than c![(a, b), for a in 0..5, for b in 0..5].

    opened by lynlevenick 0
Owner
Matt Gathu
@rust-lang all day, everyday!
Matt Gathu
A Rust macro for writing regex pattern matching.

regexm A Rust macro for writing regex pattern matching.

Takayuki Maeda 46 Oct 24, 2022
Rust crate that provides a convenient macro to quickly plot variables.

Debug Plotter This crate provides a convenient macro to quickly plot variables. Documentation For more information on how to use this crate, please ta

Fabian Bösiger 82 Dec 31, 2022
Rust macro to make recursive function run on the heap (i.e. no stack overflow).

Decurse Example #[decurse::decurse] // ?? Slap this on your recursive function and stop worrying about stack overflow! fn factorial(x: u32) -> u32 {

Wisha W. 18 Dec 28, 2022
Rust macro that uses GPT3 codex to generate code at compiletime

gpt3_macro Rust macro that uses GPT3 codex to generate code at compiletime. Just describe what you want the function to do and (optionally) define a f

Maximilian von Gaisberg 59 Dec 18, 2022
No-nonsense input!(...) macro for Rust

No-nonsense input!(...) macro for Rust

Oliver Lenehan 2 Oct 30, 2022
hado-rshado — A little macro for writing haskell-like do expressions without too much ceremony

hado Monadic haskell-like expressions brought to rust via the hado! macro What? A little macro for writing haskell-like do expressions without too muc

Lucas David Traverso 44 Jul 31, 2022
Yet another geter/setter derive macro.

Gusket Gusket is a getter/setter derive macro. Comparison with getset: gusket only exposes one derive macro. No need to derive(Getters, MutGetters, Se

Jonathan Chan Kwan Yin 2 Apr 12, 2022
A proc-macro to get Vec from struct and vise versa

byteme A proc-macro to convert a struct into Vec and back by implemeting From trait on the struct. The conversion is Big Endian by default. We have ma

Breu Inc. 11 Nov 4, 2022
Derive macro for encoding/decoding instructions and operands as bytecode

bytecoding Derive macro for encoding and decoding instructions and operands as bytecode. Documentation License Licensed under either of Apache License

Niklas Sauter 15 Mar 20, 2022
Derive macro implementing 'From' for structs

derive-from-ext A derive macro that auto implements 'std::convert::From' for structs. The default behaviour is to create an instance of the structure

Andrew Lowndes 4 Sep 18, 2022
A proc macro for creating compile-time checked CSS class sets, in the style of classNames

semester Semester is a declarative CSS conditional class name joiner, in the style of React's classnames. It's intended for use in web frameworks (lik

Nathan West 11 Oct 20, 2022
Proc. macro to generate C-like `enum` tags.

Continuous Integration Documentation Crates.io #[derive(EnumTag)] This crate provides a proc. macro to derive the EnumTag trait for the given Rust enu

Robin Freyler 5 Mar 27, 2023
A rust-based version of the popular dnsgen python utility

ripgen A rust-based version of the popular dnsgen python utility. ripgen is split into two main parts: ripgen: A CLI utility that calls into ripgen_li

resync 198 Jan 2, 2023
Pure rust implementation of python's random module with compatible generator behaviour.

pyrand Pure rust implementation of (parts of) python's random module with compatible PRNG behaviour: seeding with equivalent values will yield identic

Stefan V. 4 Feb 10, 2024
List of Persian Colors and hex colors for CSS, SCSS, PHP, JS, Python, and Ruby.

Persian Colors (Iranian colors) List of Persian Colors and hex colors for CSS, SCSS, PHP, C++, QML, JS, Python, Ruby and CSharp. Persian colors Name H

Max Base 12 Sep 3, 2022
Py-spy - Sampling profiler for Python programs

py-spy: Sampling profiler for Python programs py-spy is a sampling profiler for Python programs. It lets you visualize what your Python program is spe

Ben Frederickson 9.5k Jan 8, 2023
k-mer counter in Rust using the rust-bio and rayon crates

krust is a k-mer counter written in Rust and run from the command line that will output canonical k-mers and their frequency across the records in a f

null 14 Jan 7, 2023
Experimental Rust tool for generating FFI definitions allowing many other languages to call Rust code

Diplomat is an experimental Rust tool for generating FFI definitions allowing many other languages to call Rust code. With Diplomat, you can simply define Rust APIs to be exposed over FFI and get high-level C, C++, and JavaScript bindings automatically!

null 255 Dec 30, 2022
Aws-sdk-rust - AWS SDK for the Rust Programming Language

The AWS SDK for Rust This repo contains the new AWS SDK for Rust (the SDK) and its public roadmap. Please Note: The SDK is currently released as a dev

Amazon Web Services - Labs 2k Jan 3, 2023