gpt4 book ai didi

f# - 在 F# 中将序列包装在流中

转载 作者:行者123 更新时间:2023-12-05 00:53:33 25 4
gpt4 key购买 nike

我有一个接受流的函数。我的数据在一个大列表中,涉及数百万个项目。

有没有一种简单的方法可以将序列包装在流中,并在流中返回我的序列 block ?一种显而易见的方法是实现我自己的返回序列 block 的流类。像这样的东西:

type SeqStream(sequence:seq<'a>) = 
inherit Stream()
default x.Read(buf, offset, count) =
// get next chunk
// yield chunk

有没有更简单的方法呢?不过,我没有办法更改接受流的目标函数。

最佳答案

我认为您的方法看起来不错。唯一的问题是 Stream 是一个相对复杂的类,它有很多成员,你可能不想实现其中的大部分 - 如果你想将它传递给一些使用其中一些的代码额外的成员,您需要使实现更加复杂。不管怎样,一个只实现了 Read 的简单流看起来像这样:

type SeqStream<'a>(sequence:seq<'a>, formatter:'a -> byte[]) =
inherit Stream()

// Keeps bytes that were read previously, but were not used
let temp = ResizeArray<_>()
// Enumerator for reading data from the sequence
let en = sequence.GetEnumerator()

override x.Read(buffer, offset, size) =
// Read next element and add it to temp until we have enough
// data or until we reach the end of the sequence
while temp.Count < size && en.MoveNext() do
temp.AddRange(formatter(en.Current))

// Copy data to the output & return count (may be less then
// required (at the end of the sequence)
let ret = min size temp.Count
temp.CopyTo(0, buffer, offset, ret)
temp.RemoveRange(0, ret)
ret

override x.Seek(offset, dir) = invalidOp "Seek"
override x.Flush() = invalidOp "Flush"
override x.SetLength(l) = invalidOp "SetLength"
override x.Length = invalidOp "Length"
override x.Position
with get() = invalidOp "Position"
and set(p) = invalidOp "Position"
override x.Write(buffer, offset, size) = invalidOp "Write"
override x.CanWrite = false
override x.CanSeek = false
override x.CanRead = true

请注意,我添加了一个附加参数 - 一个将泛型类型的值转换为字节数组的函数。通常,很难将任何内容转换为字节(您可以使用一些序列化),所以这可能更容易。例如,对于整数,您可以这样写:

let stream = new SeqStream<_>([ 1 .. 5 ], System.BitConverter.GetBytes)

关于f# - 在 F# 中将序列包装在流中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6235495/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com