为什么F#';s Seq.数组的加窗返回序列

为什么F#';s Seq.数组的加窗返回序列,f#,F#,在F中,返回一个序列,其中每个窗口都是一个数组。每个窗口作为数组(一种非常具体的类型)而不是另一个序列或数组返回,这有什么原因吗?我不知道这背后的设计原则是什么。我想这可能只是实现的一个偶然方面-Seq.windowed可以通过将项目存储在数组中非常容易地实现,而Seq.groupBy可能需要使用一些更复杂的结构 一般来说,如果使用数组是自然有效的实现,我认为F#api要么使用'T[],要么返回seq,这当然是纯粹的猜测。我认为这与两种功能的实现方式有关 如前所述,在Seq.groupBy中,组

在F中,返回一个序列,其中每个窗口都是一个数组。每个窗口作为数组(一种非常具体的类型)而不是另一个序列或数组返回,这有什么原因吗?我不知道这背后的设计原则是什么。我想这可能只是实现的一个偶然方面-
Seq.windowed
可以通过将项目存储在数组中非常容易地实现,而
Seq.groupBy
可能需要使用一些更复杂的结构


一般来说,如果使用数组是自然有效的实现,我认为F#api要么使用
'T[]
,要么返回
seq,这当然是纯粹的猜测。我认为这与两种功能的实现方式有关

如前所述,在
Seq.groupBy
中,组的长度是可变的,在
Seq.windowed
中,组的大小是固定的

因此,在
Seq.windowed
的实现中,使用固定大小的数组更有意义,而不是
Seq.groupBy
中使用的
Generic.List
,顺便说一句,它在F中被称为
ResizeArray

现在对外界来说,
Array
虽然在F#code和库中广泛使用mutable,并且F#提供了创建、初始化和操作数组的语法支持,但是
ResizeArray
在F#code中没有那么广泛地使用,并且该语言除了类型别名之外没有提供语法支持,所以我想这就是为什么他们决定把它公开为一个
Seq

几个想法

首先,要知道,在当前版本中,
Seq.windowed
Seq.groupBy
都在实现中使用非惰性集合<代码>窗口化
使用数组并返回数组
groupBy
建立一个
字典>
,但将其保密,并将组值作为
seq
返回,而不是
ResizeArray

groupBy
返回
ResizeArray
s与其他任何内容都不匹配,因此显然需要隐藏。另一种方法是返回数据的
ToArray()
。这将需要创建另一个数据副本,这是一个缺点。而且这并没有多大的好处,因为你事先不知道你的团队会有多大,所以你不希望做随机访问或其他任何特殊的事情。因此,简单地用
seq
包装似乎是一个不错的选择

对于窗口化的
,情况就不同了。在这种情况下,您需要返回一个数组。为什么?因为您已经知道该阵列将有多大,所以您可以安全地进行随机访问,或者更好地进行模式匹配。这是一个很大的好处。不过,缺点仍然存在——数据需要重新复制到每个窗口新分配的数组中

seq{1 .. 100} |> Seq.windowed 3 |> Seq.map (fun [|x; _; y|] -> x + y)

还有一个悬而未决的问题——“但是我们能否通过在内部仅使用真正的惰性seq并将其返回来避免数组分配/复制的不利影响?这是否更符合‘seq的精神’?”这将有点棘手(需要一些奇特的枚举数克隆?),但当然,可能需要一些仔细的编码。不过,这有一个巨大的缺点。你需要在内存中缓存整个非工具化的seq来让它工作,这否定了懒散做事的整个目标。与列表或数组不同,多次枚举一个seq不能保证产生相同的结果(例如,返回随机数的seq),因此您要返回的这些seq窗口的备份数据需要缓存在某个地方。当该窗口最终被访问时,您不能仅仅点击并通过原始源seq重新枚举-您可能会返回不同的数据,或者seq可能在不同的位置结束。这表明了在
序列中使用数组的另一个好处。窗口化的
-只有
windowSize
元素需要一次保存在内存中。

一个原因是,数组的速度明显更快。但是,如果将它们用于无限序列,则必须调整它们的大小,因为
windowed
,大小是已知的,所以为什么不尽可能使用最快的收集类型?如果基本原理是效率,那么为什么不对
groupBy
执行相同的操作,其中组的成员也可以作为数组返回?查看:
Seq.groupBy:Seq>
为什么要将额外的
[]
添加到
seq@JohnPalmer对不起,那是个打字错误。我的意思是<代码> SEQ 确实。我从来不认为ILIST或ICLICONTION是不变的,正如<代码> Addio/Cuth>方法…运行时不变性仅仅是不够的。您能否列举一些“…F#api使用
't[]
如果使用数组是自然有效的实现,…”的例子?在的情况下,只有
toArray
windowed
seq{1 .. 100} |> Seq.windowed 3 |> Seq.map (fun [|x; _; y|] -> x + y)