6
> let a = [| 'a'..'d' |];;
val a : char [] = [|'a'; 'b'; 'c'; 'd'|]

做简单的切片:

> a.[1..2], [1..2];;
val it : char [] * int list = ([|'b'; 'c'|], [1; 2])

现在尝试使用空白区域:

> a.[1..0], [1..0];;
val it : char [] * int list = ([||], [])

似乎有效且合理 - 我们有两个空序列。

但它在这里失败了:

> a.[5..0];;
System.OverflowException: Arithmetic operation resulted in an overflow.
   at <StartupCode$FSI_0018>.$FSI_0018.main@()
Stopped due to error

当然,有一个解决方法[| for i in [5..0] -> a.[i] |]。但我错过了为什么会a.[5..0]失败?为什么不只返回空数组?这种行为有什么原因吗?

4

1 回答 1

5

这是一个错误。

尽管数组切片和范围表达式是不同的概念(例如,您不能使用a.[1..2..5]),但它们的行为应该一致。

a.[start..finish]请注意,当finish - start <= -2(失败) 时发生异常,如果( a.[3..1]),数组切片可以正常工作。finish - start = -1a.[5..4] = [||]

数组切片是通过使用prim-types.fs中的GetArraySlice函数完成的:

let inline GetArraySlice (arr: _[]) start finish = 
    let start  = (match start with None -> 0 | Some n -> n) 
    let finish = (match finish with None -> arr.Length - 1 | Some n -> n) 
    GetArraySub arr start (finish - start + 1)

whileGetArraySub在同一个模块中实现如下:

let inline GetArraySub arr (start:int) (len:int) =
    let dst = zeroCreate len   
    for i = 0 to len - 1 do 
        SetArray dst i (GetArray arr (start + i))
    dst

如果finish - start = -1,我们有len = 0GetArraySub返回zeroCreate 0一个空数组。这不再是finish - start <= -2导致len < 0zeroCreate len失败的情况。

这可以通过始终返回一个空数组来解决finish - start <= -1

于 2012-04-22T16:11:44.653 回答