为什么我不能压缩两个不同长度的列表?

时间:2017-10-28 20:30:39

标签: list f# zip

在F#中,如果试图压缩两个不同长度的列表,则会出错:

List.zip [1..4] [1..3]
// System.ArgumentException: The lists had different lengths.

但是,定义zip的替代定义非常容易,它接受两个不同长度的参数列表:

let rec zip' (xs: 'T list) (ys: 'T list) =
        match (xs, ys) with
        | ([], _) -> []
        | (_, []) -> []
        | ((z::zs), (w::ws)) -> (z, w) :: zip' zs ws

zip' [1..4] [1..3]
// val it : (int * int) list = [(1, 1); (2, 2); (3, 3)]

是否有充分的理由不使用此替代定义?为什么首先没有采用它?

1 个答案:

答案 0 :(得分:9)

这确实有点令人困惑,因为List.zip(不允许这样)和Seq.zip(截断较长的列表)之间存在不匹配。

  • 我认为zip仅适用于相等长度的列表是一种合理的默认行为 - 如果它自动截断数据,那么在使用{时,您可能会意外丢失一些有用的数据{1}}可能会导致细微的错误。

  • zip截断较长列表的事实只是合理的,因为序列是懒惰的,因此,按照设计,当我定义一个序列时,我希望消费者可能不会全部读取它。

总之,我认为行为差异是基于“对于给定的数据结构最明智的事情是什么”,但我确实认为为操作设置两个名称比调用两个名称更有意义{ {1}}(唉,现在几乎不可能改变)。