> let a = [| 'a'..'d' |];;
val a : char [] = [|'a'; 'b'; 'c'; 'd'|]
Run Code Online (Sandbox Code Playgroud)
做琐碎的切片:
> a.[1..2], [1..2];;
val it : char [] * int list = ([|'b'; 'c'|], [1; 2])
Run Code Online (Sandbox Code Playgroud)
现在尝试使用空白区域:
> a.[1..0], [1..0];;
val it : char [] * int list = ([||], [])
Run Code Online (Sandbox Code Playgroud)
似乎工作和合理 - 我们有两个空序列.
但它失败了:
> a.[5..0];;
System.OverflowException: Arithmetic operation resulted in an overflow.
at <StartupCode$FSI_0018>.$FSI_0018.main@()
Stopped due to error
Run Code Online (Sandbox Code Playgroud)
当然,有一种解决方法[| for i in [5..0] -> a.[i] |]
.但我想念a.[5..0]
失败的原因?为什么不直接返回空数组?这种行为有什么理由吗?
这是一个错误.
虽然数组切片和范围表达式是不同的概念(a.[1..2..5]
例如,您不能使用),但它们应该表现一致.
请注意,异常发生在a.[start..finish]
when finish - start <= -2
(a.[3..1]
失败)和数组切片工作正常if finish - start = -1
(a.[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)
Run Code Online (Sandbox Code Playgroud)
虽然GetArraySub
在同一个模块中实现如下:
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
Run Code Online (Sandbox Code Playgroud)
如果finish - start = -1
,我们len = 0
进入GetArraySub
并zeroCreate 0
返回一个空数组.它不再是finish - start <= -2
导致len < 0
和zeroCreate len
失败的情况.
这可以通过始终返回空数组来解决finish - start <= -1
.