#tuple #extension #map #and-then

keepops

映射函数输入的扩展特性

2 个版本

0.0.2 2022年12月8日
0.0.1 2022年11月3日

#2449 in Rust 模式

MIT 许可证

16KB
333

Keepops

该库读作 "kee-pops"。它是一个用于处理 Rust 和元组的函数式编程功能的实用库。

用例

你是否曾经编写过这样的 Rust 代码?

fn some_fallible_function() -> Option<usize> { Some(0) }
fn some_other_fallible_function(x: usize) -> Option<usize> { Some(0) }
fn double(a: usize) -> usize { 2 * a }

some_fallible_function().map(|input| (input, double(input)));

some_fallible_function().and_then(|input| some_other_fallible_function(input).map(|result| (input, result)));

vec![1,2,3].into_iter().map(|input| (input, double(input)))

你: "嗯,有时候。这种显式的输入到结果元组传递可能有点烦人,但还可以管理 :)"

那么这个呢?

fn some_function_with_many_outputs() -> (usize, usize, usize) { (0, 0, 0) }
fn some_fallible_function() -> Option<usize> { Some(0) }

some_fallible_function().map(|(a,b,c)| (a, b, c, a + b + c))

"嗯,好吧。我明白了,但我认为它不是太... "

...那么这个稍微更实际的例子呢?!?

pub struct Apple;
pub struct Banana;
pub struct Chocolate;
pub struct AppleBananaChocolateCakeRecipe;
pub struct AppleBananaChocolateCake;

fn try_gather_fruits() -> Option<(Apple, Banana)> {
  Some((Apple, Banana)) 
}
fn get_some_chocolate_and_hold_onto(apple: &Apple, banana: &Banana) -> Chocolate {
  Chocolate 
}
fn search_for_recipe_in_book_shelf_while_carrying(
  apple: &Apple,
  banana: &Banana,
  chocolate: &Chocolate
) -> Option<AppleBananaChocolateCakeRecipe> {
  Some(AppleBananaChocolateCakeRecipe) 
}
fn bake_cake(
  apple: Apple,
  banana: Banana,
  chocolate: Chocolate,
  recipe: &AppleBananaChocolateCakeRecipe
  ) -> AppleBananaChocolateCake {
  AppleBananaChocolateCake
}

try_gather_fruits()
  .map(|(apple, banana)| {
    let chocolate = get_some_chocolate_and_hold_onto(&apple, &banana);
    (apple, banana, chocolate)
  })
  .and_then(|(apple, banana, chocolate)| {
    search_for_recipe_in_book_shelf_while_carrying(&apple, &banana, &chocolate)
      .map(|recipe| (apple, banana, chocolate, recipe))
  })
  .map(|(apple, banana, chocolate, recipe)| bake_cake(apple, banana, chocolate, &recipe))

" ... "

正如你所见,有时映射可能会变得有些杂乱和冗长。但是有一个解决方案:我们可以用一些显式的输入传递来换取一些隐式内部线程的输入。使用 keepops,上面的例子将看起来像这样。


try_gather_fruits()
  .keep_tuple_map(|(apple, banana)| get_some_chocolate_and_hold_onto(apple, banana))
  .keep_tuple_and_then(|(apple, banana, chocolate)| search_for_recipe_in_book_shelf_while_carrying(apple, banana, chocolate))
  .map(|(apple, banana, chocolate, recipe)| bake_cake(apple, banana, chocolate, &recipe))

是不是更流畅了?

"嗯,但是... "

嘘,我知道,我知道。它并不完美,但它减少了重复,这正是它的全部意义。如果你不想用,也可以不用。

限制

  • 像大多数基于元组的库功能一样,该函数只适用于有限项数的元组。大多数库选择 8 个项数,所以我只是为了好玩选择了 16 个。
  • 该库使用不稳定但即将稳定的特性 泛型关联类型
  • 请注意,这些函数可能带来一些开销

没有运行时依赖