2016-07-03 3 views
1

私はVecを取り、その位置に基づいてその値の一部を取り除く関数downsample_vecを持っています。私は(私だけCloneIndexを必要としますが、それを動作させることができませんでした)トラブル右の特性に注釈を付けるを持っていたので、私は私が右の推論を行うために、コンパイラを納得させることができるかどうかを確認するためにselfを使用することにしました:ライブラリ内の固有の型を拡張するのは悪い形ですか?

impl Vec<IndexMut<usize>> { 
    fn downsample<usize>(&mut self, factor: usize) { 
     let len = self.len(); 
     if factor > len { 
      self.clear(); // downsample factor skips all elements 
     } else if factor == 1 { 
      return; // no actual downsampling 
     } 

     for ind in 0..len() { 
      if ind % factor != 0 { 
       self.remove(ind); 
      } 
     } 
    } 
} 

コンパイルエラーthe value of the associated type `Output` (from the trait `std::ops::Index`) must be specified [E0191]を返します。

私は、出力タイプを指定する方法を正確にはわからない、とちょうど一般的で特色にブログ、これを行う方法上の任意の参照を見つけることができませんでした。私の主なリソースはthe rust vec .retain() sourceでした。

それが最初の場所で特定のライブラリでは、このような局部的にモンキーパッチVecに悪い形で、またはこれを行うには正しい方法は何ですか? (私が書いたオリジナルの分離機能は、the playgroundで見ることができます)。

答えて

4

コードにはいくつかの点があります。

まず、あなたがあなた自身のクレートに定義されていないタイプのimpl - ブロックを書き込むことはできません。あなたができることは、新しい形質を定義して、その型を外国の型に対して実装することです。これは一般的なプラクティスであり、しばしば「拡張特性」と呼ばれ、のような名前付けスキーム*Extを使用して行われます。

trait DownsampleExt { 
    fn downsample(&mut self, factor: usize); 
} 

は、今、私たちはVecのためにそれを実装する必要がありますので、のようなので、我々はそれを構築することができます。あなたのコードでは、ベクトル自体が可変インデックス可能であるかどうかを確認したい場合と同様にIndexMutの特性を使用します。しかし、Vecはすでに具体的な型(または型コンストラクタ)なので、コンパイラはすでにそれが可変インデックス可能であることを既に知っています。だから、これはすでに作品:

impl<T> DownsampleExt for Vec<T> { 
    fn downsample(&mut self, factor: usize) { 
     // action code 
    } 
} 

DownsampleExt形質がスコープ内にある場合、あなたはどのVecオブジェクトにdownsampleを呼び出すことができます。

あなたのアクションコードは、しかし、まだいくつかのバグが含まれています/いくつかの問題があります。

  • あなたは「それはVecとを取り、少ない値でそのコピーを返す」、しかし、あなたが与えたコードと私たちはコピーを作る代わりにベクトルを変異させます!あなたの記述があなたのコードと一致しないことに注意してください。
  • factor == 0
  • あなたforループが動作しないためにあなたはチェックしません。私たちはインデックスを反復処理しながら、要素を削除すると、インデックスを無効にします。ある要素を削除するときは、その反復でインデックスを増やしてはいけません。
  • removeは線形時間アルゴリズムなので、アルゴリズムはO(n²)で実行されます。これはあなたが望むものではないかもしれません。機能記述問題を指摘して
+0

感謝。私はあまりにも多くの編集をして、私はそれを乱して質問に微調整していた。 –

関連する問題