2024年6月8日发(作者:)

Filters, sources and sinks: design, motivation and examples

or Functional programming for the rest of us

by DiegoNehab

应用程序有时有太多的信息需要在内存处理,即使现在已经有足够的内存,也会被迫

把数据分成小部分处理。,以原子方式处理所有数据可能需要很长的时间,这妨碍了用户

与应用程序交互。复杂的数据转换往往可以被定义为一系列简单的操作。几个不同的复杂

的转换可以共享相同的更简单的操作,因此,定义一个统一的接口,把他们组合起来,是

很好的处理方法。以下概念构成我们对这些问题的解决方案。

Filters是一些函数,接受连续块的输入,并产生连续的输出块。此外,连接所有的输

出数据作为输入数据的级联filter应用的结果是相同的。因此,边界是无关紧要的:

Filters必须处理由用户任意分割的输入数据。

chain是一个函数,将两个(或更多)的函数连接起来,但其接口和其他函数组件的

接口没有什么区别。因此,链式Filters可用于任何一个可以使用原子Filter的地方。然

而,其对数据的影响是其组成的filters的综合效果。请注意, chain可以连接其他的

chain,创建任意复杂的操作,而像原子操作那样使用。

Filter可以被看作是通过它的数据流在网络内部的节点,并且可能根据不同的filter

对数据进行转换。把这些节点链接起来,组成完整的网络数据流图。为此我们需要添加初

始和最终的网络节点,分别是source和sink。具体来说,source是一个函数,每次调

用时产生新的数据。相应的,sink函数是接收到的数据的最终目的地。source和sink可

以使用chain和filter相连。

总的来数,Filter,chain,source和sink,都是被动的实体:他们需要被重复调用

以便使系统运行起来。Pumps提供了推动数据流过网络的动力,从一个source到一个

sink。

我们希望,通过例子使这些概念将变的清晰。在下面的章节中,我们从一个简单的接

口开始,不断的完善这个接口,直到没有明显的缺点。我们做出的演化不是人为强制的:

它按部就班,巩固了我们对这些概念的理解。

1

一个具体的例子

一些数据转换操作容易用Filter方式来实现,比如行结束的文本标准化,Base64和

Quoted-Printable传输内容的编码,把文本切分成行,SMTP字节填充等等。我们将要

定义第一个filter接口,“行结束符标准化”。稍后我们讨论为什么实现起来并不容易。

假设我们得到一个文本,含有未知的行结束符,比如常见的Unix(LF)的Mac操作

系统(CR)和DOS(CRLF)(包括可能的混合情况)。我们希望能够编写如下代码:

input = ((), normalize("rn"))

output = ()

2