在F#中如果试图压缩两个不同长度的列表,则会出现错误:
List.zip [1..4] [1..3]
// System.ArgumentException: The lists had different lengths.
Run Code Online (Sandbox Code Playgroud)
但是,定义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)]
Run Code Online (Sandbox Code Playgroud)
是否有充分的理由不使用这种替代定义?为什么不首先采用它?
Tom*_*cek 11
实际上,这有点令人困惑,因为List.zip(不允许这样)和Seq.zip(截断较长列表)之间存在不匹配.
我认为zip仅适用于长度相等的列表是一种合理的默认行为 - 如果它自动截断数据,那么在使用时zip可能会意外丢失一些有用的数据,这可能会导致细微的错误.
Seq.zip截断较长列表的事实只是合理的,因为序列是懒惰的,因此,在设计时,当我定义一个序列时,我希望消费者可能不会全部读取它.
总而言之,我认为行为差异是基于"对于给定的数据结构最明智的事情是什么",但我确实认为有两个操作名称会比调用两个名称更有意义zip(唉,那是现在几乎无法改变).