2015-01-10 7 views
8

私は非常にうまくいけば、スライスで遊んでいます。スライス上のインデックス作成操作の戻り値の型は何ですか?

私は私の最初の問題が減少している。しかし、コンパイラは私を与え

pub trait Index<Index> { 
    type Output; 
    fn index(&'a self, index: &Index) -> &'a <Self as Index<Index>>::Output; 
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
} 

slice[index]の戻り値の型がdocumentation与えられた基準、ことが私の予想である

fn at<'a, T>(slice: &'a [T], index: usize) -> &'a T { 
    let item = slice[index]; 
    item 
} 

エラー:

error: mismatched types: expected &'a T , found T (expected &-ptr, found type parameter)

  item 
      ^~~~ 

私はmeaと解釈しますitemの型が関数の戻り値の型と一致していないことを確認しました(私はitemをデバッグ目的のためだけに導入し、式評価をreturnから分割しました)。

戻り値の型をitemTに変更すると、明らかに借り入れから移動するというエラーメッセージが表示されます。

ビットをいじった後、私は最終的に2の回避策を得た:

fn at<'a, T>(slice: &'a [T], index: usize) -> &'a T { 
    &slice[index] 
    ^
} 

fn at<'a, T>(slice: &'a [T], index: usize) -> &'a T { 
    let ref item = slice[index]; 
     ^~~ 
    item 
} 

は、トリックを行う基準となるタイプを強制的に。

しかし、なぜそれらの嫌悪感は最初に必要ですか?何か間違っていますか?

答えて

8

これは、コードをもっとよく見せるために、コンパイラがあなたに役立つエルゴノミクスのビットです。 Indexトレイト

戻り値は参照ですが、砂糖の構文[]を使用する場合、コンパイラが自動的のための間接参照を挿入します。他のほとんどの言語は、配列からアイテムを返すだけです(オブジェクトをコピーしたり、オブジェクトへの別の参照を返すなど)。インデックス値があることを

let items = &[1u8, 2, 3, 4]; 

let a: u8 = items[0]; 
let a: u8 = *items.index(&0); // Equivalent of above 

let b: &u8 = &items[0]; 
let b: &u8 = &*items.index(&0); // Equivalent of above 

注:これらのケースでは、あなたが通常&を使用しますのでにより移動/コピー・セマンティクスの錆の重要性に

、あなたは常に、コピーに値を作成することはできません自動的に逆参照と同様に参照によって自動的に取得されます。

+0

ああ!わかりましたので、私は[]の砂糖につかまってしまいました!私は '' T 'を '' T' 'が '' T' 'を使って '' index'を呼び出すことに賛成するという違いをすでに知っていましたが、違いを期待していなかったので、 ''インデックス 'イラストをありがとう、本当に物事を視覚化するのに役立ちます。 –

5

いいえ、すべて正しく行っています。 index()メソッドは参照を返しますが、インデックス操作で呼び出されると、その結果は自動的に逆参照されます。これは索引付けがより自然なものになるように行われます。ある種の索引演算子が存在するすべての言語(主にCおよびC++)では、参照をコンテナに戻すのではなく、値自体を戻します。

コレクションへの参照を取得するには、参照演算子を明示的に適用するか(最初の「回避策」のように)、参照パターンを使用する必要があります。

関連する問題