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 = ([||], [])

機能していて妥当なようです - 2 つの空のシーケンスが得られました。

しかし、ここでは失敗します:

> 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]when finish - start <= -2a.[3..1]fail)で発生し、配列スライシングはif 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 = 0、空の配列を返しますGetArraySub。につながることや失敗するzeroCreate 0ことはもはやありません。finish - start <= -2len < 0zeroCreate len

これは、常に空の配列を返すことで修正できますfinish - start <= -1

于 2012-04-22T16:11:44.653 に答える