2017-10-28 114 views
3

在F#如果试图向拉链不同长度的两个列表一个得到一个错误:为什么我不能压缩两个不同长度的列表?

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

然而,这是很容易定义拉链的可替换定义,接受两个不同长度的自变量列表:

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)] 

有没有很好的理由不使用这个替代定义?为什么不首先采用?

回答

7

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

  • 我认为zip仅在长度相等的名单作品是一个合理的默认行为 - 如果它会自动截断数据,有可能使用zip时,这可能会导致你会不小心丢失了一些有用的数据现实机会微妙的错误。

  • Seq.zip截断较长列表的事实仅仅是明智的,因为序列是懒惰的,所以在设计中,当我定义一个序列时,我期望消费者可能不会阅读全部。

综上所述,笔者认为,行为差异是基于“什么是最明智的事情对于一个给定的数据结构做”,但我认为其对操作的两个名字会使很多更有意义比调用zip(唉,这几乎不可能改变现在)。

+0

如果我们根据它们的行为为库函数赋予不同的名字,我们还需要为'exist2','forall2','iter2','map2' – kaefer

相关问题