Sink 操作
探索用于变换、过滤和适配 Sink 的操作,从而在 Stream 处理中实现自定义的输入输出处理与元素过滤。
在前面几节中,我们学习了如何创建和使用 Sink。现在,让我们来探索一些可以变换或过滤 Sink 行为的操作。
适配 Sink 的输入
有时,你的 Sink 处理的是一种输入类型,而当前的 stream 使用的是另一种类型。Sink.mapInput 函数通过变换输入值,帮助你让 Sink 适配新的输入类型。Sink.map 改变的是 Sink 的输出,而 Sink.mapInput 改变的是它接受的输入。
示例(将字符串输入转换为数值以便求和)
假设你有一个用于计算数字之和的 Sink.sum。如果你的 stream 中包含的是字符串而不是数字,那么 Sink.mapInput 可以把这些字符串转换为数字,从而让 Sink.sum 能与你的 stream 配合工作:
import { Stream, Sink, Effect } from "effect"
// A stream of numeric strings
const stream = Stream.make("1", "2", "3", "4", "5")
// Define a sink for summing numeric values
const numericSum = Sink.sum
// Use mapInput to adapt the sink, converting strings to numbers
const stringSum = numericSum.pipe(
Sink.mapInput((s: string) => Number.parseFloat(s)),
)
Effect.runPromise(Stream.run(stream, stringSum)).then(console.log)
// Output: 15
同时变换输入与输出
当你需要同时变换 Sink 的输入和输出时,Sink.dimap 提供了一个灵活的解决方案。它扩展了 mapInput:允许你先变换输入类型、执行操作,再把输出变换为新类型。这在需要在输入类型和输出类型之间做完整转换时很有用。
示例(将输入转换为整数、求和,再把输出转换为字符串)
import { Stream, Sink, Effect } from "effect"
// A stream of numeric strings
const stream = Stream.make("1", "2", "3", "4", "5")
// Convert string inputs to numbers, sum them,
// then convert the result to a string
const sumSink = Sink.dimap(Sink.sum, {
// Transform input: string to number
onInput: (s: string) => Number.parseFloat(s),
// Transform output: number to string
onDone: (n) => String(n),
})
Effect.runPromise(Stream.run(stream, sumSink)).then(console.log)
// Output: "15"
过滤输入
Sink 还可以借助 Sink.filterInput 按特定条件过滤传入的元素。这个操作让 Sink 只处理满足特定条件的元素。
示例(按每三个一组过滤负数)
在下面的示例中,元素被收集为每三个一组,但只有正数会被包含进来:
import { Stream, Sink, Effect } from "effect"
// Define a stream with positive, negative, and zero values
const stream = Stream.fromIterable([
1, -2, 0, 1, 3, -3, 4, 2, 0, 1, -3, 1, 1, 6,
]).pipe(
Stream.transduce(
// Collect chunks of 3, filtering out non-positive numbers
Sink.collectAllN<number>(3).pipe(Sink.filterInput((n) => n > 0)),
),
)
Effect.runPromise(Stream.runCollect(stream)).then((chunk) =>
console.log("%o", chunk),
)
/*
Output:
{
_id: 'Chunk',
values: [
{ _id: 'Chunk', values: [ 1, 1, 3, [length]: 3 ] },
{ _id: 'Chunk', values: [ 4, 2, 1, [length]: 3 ] },
{ _id: 'Chunk', values: [ 1, 1, 6, [length]: 3 ] },
{ _id: 'Chunk', values: [ [length]: 0 ] },
[length]: 4
]
}
*/