#function #pipe #macro #composition #elixir

pike

一个宏集合,用于管道 |> 函数调用,类似于 F#、Elixir 和 OCamel 等函数式语言。

7 个版本

0.1.6 2024 年 6 月 21 日
0.1.5 2024 年 6 月 21 日

#379Rust 模式

Download history 318/week @ 2024-06-17 3/week @ 2024-06-24 179/week @ 2024-07-08 66/week @ 2024-07-15 82/week @ 2024-07-22 233/week @ 2024-07-29 72/week @ 2024-08-05

每月 511 次下载
4 个 crate 中使用 (通过 git-next-core)

MIT/Apache

14KB
229

Pike - PipeLike

Pike 是一个宏集合,用于管道你的函数调用,类似于 F#、Elixir 和 OCamel 等函数式语言。

示例

管道操作符 |> 允许你以灵活的方式建立函数“管道”。

TL;DR

// takes a string's length, doubles it and converts it back into a string
let len = pike! {
  "abcd"
  |> str::len
  |> (as u32)
  |> (times(2))
  |> &
  |> u32::to_string
};

// same as

let len = times("abcd".len() as u32, 2).to_string();
fn times(a: u32, b: u32) -> u32{
    a * b
}

fn times2(n: u32) -> u32 {
    times(n, 2)
}

// Passes the preceding expression as the only argument of proceding function.
let num = pike! {
  2
  |> times2
  |> times2
};
assert_eq!(num, 2 * 2 * 2);

// Passes the preceding expression as the first argument of proceding function.
// by wrapping the function in parentheses we can pass the remanining arguments by partially
// calling the `times` as `times(?, 2)` and passing 2 as its first argument via the pipeline.
let num = pike! {
  1
  |> (times(2))
  |> (times(3))
};
assert_eq!(num, 1 * 2 * 3);

// call a method using pipelines
let len = pike!("abcd" |> str::len);
assert_eq!(len, "abcd".len());

// Closures can also be pipelined similar to partial functions.
let c = pike! {
  ['a', 'b', 'c', 'd']
  |> (|it: [char; 4]| it[2])
};
assert_eq!(c, 'c');

// Piping through `&` symbol would get a reference to the preceding expression.
let it = "it";
let is_it = |r: &&str| it == *r;

let is_it = pike! {
  it
  |> &
  |> is_it
};
assert_eq!(is_it, true);


// There are also special macros for options and results but those already have an ergonomic API for chaining.

let data = pike_opt!(id |> get_cached |> fetch_local |> fetch_remote);
// same as get_cached(id).or_else(|| fetch_local(id)).or_else(|| fetch_remote(id));

let result = pike_res!("http://rust-lang.net.cn" |> download |> parse |> get_links);
// same as download("http://rust-lang.net.cn").map(parse).map(get_links);

  • pike! 是“标准”管道宏
  • pike_res!pike! 类似,但只接受返回 Result(同一类型)的函数,并在结果为 Err 时提前返回。对于组合多个 IO 转换(如打开文件、读取内容并执行 HTTP 请求)非常有用。
  • pike_opt!pike! 类似,但只接受返回 Option(同一类型)的函数。只要所有函数返回 None,管道将始终在初始值上继续操作。如果管道中的函数返回 Some,则宏将提前返回该值。如果想要按指定顺序尝试多个函数以查看哪个函数可以利用该值,这可能非常有用。

语法特性

任何 pike 都以表达式作为初始值开始,并要求你指定一个转换该初始值的函数。

let result = pike!(2 |> times2);
// same as times2(2)

如果你添加括号,就像正常函数调用一样,传递的参数将在转换后的值之后应用于该函数。

let result = pike!(2 |> (times(2)));
// same as times(2, 2)

你可以传递闭包 \o/!闭包必须用括号括起来。

let result = pike! {
  2
  |> (times(2))
  |> (|i: u32| i * 2)
};
// same as (|i: u32| i * 2)(time(2, 2))

如果你想要将函数作为转换值的方调用,只需将其作为路径传递。

let result = pike!("abcd" |> str::len);
// same as "abcd".len()

许可证

许可方式为以下之一

任选其一。

Pike 是 pipeline.rs 的精神继承者,并从该项目中继承了许可证。

贡献

除非您明确说明,否则根据Apache-2.0许可证定义,您提交的旨在包含在作品中的任何贡献将双许可,如上所述,没有任何附加条款或条件。

无运行时依赖