#chain #utility #no-std

no-std chain_tools

一组特性,允许以更优雅的方式编写链式编程

3个不稳定版本

0.2.0 2023年5月31日
0.1.1 2023年3月17日
0.1.0 2023年3月16日

2995Rust模式

每月下载量 36

MIT/Apache

8KB
81

Chain tools: Rust本应如此

chain_tools 是一个库,旨在将每个函数都转换为一条长链式函数。灵感来源于学习Haskell,并发现自己对列表解析的限制感到沮丧。

关于列表解析的一番不算简短的牢骚

对于那些可能不知道的人来说,列表解析旨在成为一种快速定义基于某些其他列表的新列表的方法。例如,在Python中,你可以写 [x*x for x in range(10) if x % 2 == 0]。这将返回小于10的每个偶数的平方。在Haskell中,这将是 [x^2 | x <- [0..9], even x]。起初,这种语法可能看起来很复杂,特别是在Haskell中,单词被符号替换,但很快就会变得容易阅读。问题是混淆。

一个特性让人困惑并不是问题。毕竟,我爱Rust,这是一种许多人认为最难学和最让人困惑的语言。这些情感并不错。开始学习Rust时,你学到的每个新功能都伴随着十层新的复杂性。这种复杂性可能会让语言对初学者来说更难,但它存在是有原因的。一旦你理解了这些复杂的系统,它们给予你的力量是无与伦比的。Rust的类型系统很复杂,但它也是任何语言的最佳功能。

明确了这一点之后,让我们回到列表推导式。Rust没有列表推导式。Rust不需要列表推导式。Rust有更好的东西。当面对给开发者提供一种简单的方式来转换列表的任务时,Python和Haskell遇到了问题。它们的语言并没有围绕这种任务来设计。在Python中,你甚至不能在某个函数(如len(list))的包装下找到列表的长度。添加这种功能实际上需要全新的语法。Haskell决定将整个语言围绕列表推导式来构建。我要给他们一些赞誉,它确实看起来非常“数学化”。

当Rust面临这个相同的问题时,许多前期工作已经完成。迭代器特性已经可以通过.filter().map()方法来扩展。如果你将它们结合起来,你将得到.filter_map()函数,它做的是与列表推导式完全相同的事情。功能是相同的。以下是一些Rust代码示例来演示:(0..10).filter_map(|x| (x % 2 == 0).then(|| x * x))。你还可以单独使用这两个方法,如下所示:(0..10).filter(|x| x % 2 == 0).map(|x| x * x)

那么它的意义是什么呢?我可以看到很多人更喜欢列表推导式的样式,而不是Rust的过滤和映射。我甚至不能说他们是错的,毕竟外观是主观的,但有一些真理需要牢记。

真理#1: 列表推导式打乱了顺序。

大多数编程语言按照以下顺序操作:从上到下,从左到右。列表推导式打乱了第二个顺序。首先得到输出,然后是定义,然后是源,然后是条件。《这是》《从》《这个》《当》《这个》时。《这可能不是什么大问题,但代码本身可能已经很难阅读,而打乱顺序只会使阅读更加困难》。

真理#2: 列表推导式不灵活。

列表推导只能做四件事。筛选、映射、筛选-映射或复制。如果你想先映射再筛选呢?如果想链接着另一个列表呢?如果想折叠值呢?你可以做这些事,当然可以,但可能需要将多个推导语句链在一起,或者完全放弃使用。这个旨在让生活更美好的功能,由于它的不可灵活性,在许多情况下都变得毫无用处。

这正是Rust的亮点所在。能够一个接一个地链式调用迭代器函数调用,这提供了真正的灵活性。先筛选后映射?iter.filter().map()。先映射后筛选?iter.map().filter()。另一个筛选和映射?

iter
  .filter()
  .map()
  .filter()
  .inspect()
  .cycle()
  .skip(5)
  .filter_map()
  ...

这可以持续到你需要的程度。关键就在这里。无论何时你需要,这个系统都足够灵活,可以完成你想要的任务,并在执行过程中保持可读性。无论链有多长,序列始终不变。逻辑从函数到函数清晰易懂,从不中断。

  • 待办事项:添加更多抱怨。

无运行时依赖