我正在尝试向Seq模块添加一些额外的聚合函数.我在看这里列出的一些函数的实现:
https://github.com/fsharp/fsharp/blob/master/src/fsharp/FSharp.Core/seq.fs
其中一个免责声明是"该函数返回一个序列,一旦该序列被迭代,就会消化整个初始序列.因此,该函数不应该用于大序列或无限序列." 许多功能都是如此,例如GroupBy.
第一个问题:是否有方法可以编写可以有效处理大型序列的聚合函数?我知道"大"是主观的; 我只是在寻找编写这些函数的一般模式.
第二个问题:我如何确保像Dictionary这样的集合(在集合函数中定义)被有效地垃圾收集?我理解字典应该在超出范围时收集,但有没有办法明确表明?鉴于字典的范围是保留在函数内,我不能在那上面调用.Clear()吗?
回答你的第一个问题 - 在这种情况下,大输入的问题是必须在函数之前处理整个序列,fold或者groupBy可以给出结果.你可以做一些事情:
使用类似Seq.scan聚合值的函数,fold但在添加每个元素后产生当前状态 - 结果也是序列,您可以懒得消耗它(例如,获得越来越精确的结果).
在编写返回的函数时seq<'a>,您应该设计它们,以便从序列中获取下一个元素只会消耗一些可预测数量的输入元素(但不是整个输入序列).这是不可能的,例如groupBy,但您可以编写类似分组的构造,该构造仅对同一组的相邻元素进行分组.
要回答第二个问题 - 你通常不应该过多担心垃圾收集器.在功能结束时强制进行垃圾收集可能会造成更多伤害,而不仅仅是依靠GC才能正常工作.