2017-09-24 15 views
3

配列と文字列のインデックスは、なぜ微妙に異なる構文を使用するのですか?文字列と配列のインデックスの構文

など。

let _: int = [|1;2;3|].(0) 
let _: char = "123".[0] 

I(およびその他)は、これが奇妙で混乱していると判断します。 OCamlのアドホック多型/関数のオーバーロードとインデックスオペレータが現在のOCamlの関数の形として考えられ、このように対象とされて見送る:OCamlはフロート追加ため整数加算用++.を使用することとまったく同じ理由

答えて

5

関数と同じ制限。

はより正確には、インデックス演算子は現在、非常に浅いシンタックスシュガーです:パーサはx.(n)Array.set x n yからArray.get x nにとx.(n) <- y書き換えて(またはArray.unsafe_getArray.unsafe_set-unsafeオプションでコンパイルされている場合)。同様に、 s.[n]String.get s nに書き換えられ、s.[n]<-xString.set s n xになります。

これは、新しいArrayモジュールを定義することによって、独自のインデックス演算子を定義することが可能であることを意味します。ハックこの種のコードは、将来的に動作するという保証がないこと

module Array = struct 
    include Array 
    let get a n = get a (n-1) 
    let unsafe_get a n 
end 
;; [|1|].(1) 

注:たとえば、以下の無分別 トリックは、配列のインデックスは1から開始いたします。独自のインデクシング演算子を定義したい場合は、ドット.と左括弧((,[,{のいずれか)の間に少なくとも1つの(演算子)文字を挿入して拡張インデックス演算子を定義することが可能です。

let (.?()) dict key = Dict.find_opt dict key 

あなたは、どういうわけか、少ないインデックス演算子をご希望の場合は、配列のようなデータ型のプリミティブ操作ではなく、関数呼び出しをインデックスを作成する命題があります。これにより、すでにレコードフィールドに対して行われているように、型指向の曖昧さ回避を使用することができます。これは、タイプチェッカーがタイプ情報を使用してどのプリミティブ操作を使用すべきかを解決するので、両方とも

let first (s:string) = s.(0) 
let first (a: _ array) = a.(0) 

となる可能性があることを意味します。

しかし、この提案はまだ進行中です(https://github.com/ocaml/ocaml/pull/616参照)。そのため、文字列とジェネリック配列のインデックスを構文で区別する必要があります。