pipelining-macro

Crates.iopipelining-macro
lib.rspipelining-macro
version0.1.0
created_at2025-04-24 03:13:13.46093+00
updated_at2025-04-24 03:13:13.46093+00
descriptionA convenience macro for the pipeline syntax pattern
homepage
repositoryhttps://github.com/alexander-novo/pipelining-macro
max_upload_size
id1646574
size9,691
Alexander Novotny (alexander-novo)

documentation

README

pipelining-macro

The pipe! macro allows for nested function evaluations which are written left to right, rather than inside out (and often right to left) similarly to pipes in shells or the pipe operators in C++, Elixir, or F#.

Usage Examples

A basic usage is given as follows:

use pipeline_macro::pipe;

fn fn1(x: i32) -> i32 {x+1}
fn fn2(x: i32) -> i32 {2*x}
let x = 5;

assert_eq!(
	pipe!(x+2 => fn1 => fn2),
	fn2(fn1(x+2))
);

Functions which take multiple arguments as input are supported - you simply need to specify which arguments to pipe into using the wildcard (_):

use pipeline_macro::pipe;

fn fn1(x: i32) -> i32 {x+1}
fn fn2(x: i32, y:i32) -> (i32, i32) {(x, y)}
let x = 5;
let y = 1;

assert_eq!(
	pipe!(x+2 => fn1 => fn2(y, _)),
	fn2(y, fn1(x+2))
);

Note that the output from all previous function evaluations will be inserted into each wildcard character, although previous functions will only be executed only once:

# use pipeline_macro::pipe;
# fn fn1(x: i32) -> i32 {x+1}
# fn fn2(x: i32, y:i32) -> (i32, i32) {(x, y)}
# let x = 5;
# let y = 1;
#
assert_eq!(
	pipe!(x+2 => fn1 => fn2(_, _)),
	fn2(fn1(x+2), fn1(x+2))
);

Expressions which can be evaluated like a function (such as lambdas) are also supported:

use pipeline_macro::pipe;

fn fn2(x: i32, y:i32) -> (i32, i32) {(x, y)}
let x = 5;
let y = 1;

assert_eq!(
	pipe!(x+2 => |x| x-1 => fn2(_, y)),
	fn2((|x| x-1)(x+2), y)
);

Note that to support expressions which can be evaluated like a multi-argument function need to be parenthesized before specifying which arguments are piped:

# #![feature(macro_metavar_expr)]
# use paste::paste;
# 
# // A macro which partially evaluates a function
# macro_rules! bind {
# 	($($f:ident).+ ($($($head:expr_2021),*,)? $(_ $(, $tail:expr_2021)*),*)) => {
# 		paste! {
# 			|$([<x ${index()}>] $(${ignore($tail)})*),+| {
# 				$($f).+($($($head),*,)? $([<x ${index()}>] $(, $tail)*),*)
# 			}
# 		}
# 	};
# 	($($f:ident).+ ($($head:expr_2021),*)) => {
# 		|| {
# 			$($f).+($($head),*)
# 		}
# 	};
# }
use pipeline_macro::pipe;

fn fn1(x: u16, y: u16, z: u16) -> (u16, u16, u16) {
	(x, y, z)
}

let x = 1;
let y = 2;
let z = 3;

assert_eq!(
	pipe!(x => (bind!(fn1(_, _, z))) (_, _)),
	fn1(x, x, z)
);

In the above example, bind!(fn1(_, _, z)) can be evaluated like a function with two arguments.

Commit count: 6

cargo fmt