在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)]
是否有充分的理由不使用此替代定义?为什么首先没有采用它?
答案 0 :(得分:9)
这确实有点令人困惑,因为List.zip
(不允许这样)和Seq.zip
(截断较长的列表)之间存在不匹配。
我认为zip
仅适用于相等长度的列表是一种合理的默认行为 - 如果它自动截断数据,那么在使用{时,您可能会意外丢失一些有用的数据{1}}可能会导致细微的错误。
zip
截断较长列表的事实只是合理的,因为序列是懒惰的,因此,按照设计,当我定义一个序列时,我希望消费者可能不会全部读取它。
总之,我认为行为差异是基于“对于给定的数据结构最明智的事情是什么”,但我确实认为为操作设置两个名称比调用两个名称更有意义{ {1}}(唉,现在几乎不可能改变)。