2017-12-04 14 views
-4

私はRustのライフタイムの基本とiteratorでのイテレータの使い方を理解しましたが、それでもタプルの繰り返しが可能で、ヒープに割り当てられたタプルのiterableを返す関数を定義するのには問題があります。参照のIntoIteratorを取得し、変更された値への参照のボックス化された反復子を返す方法はありますか?

(私は "反復可能" はルーストに何を意味するものではありませんが、私はまだIntoInteratorの代わりに使用することを知っている)

use std::iter::{once, repeat}; 

fn foo<'a, I>(costs: I) -> Box<Iterator<Item = &'a (i32, f32)>> 
where 
    I: IntoIterator<Item = &'a (usize, f32)>, 
{ 
    let preliminary_examination_costs = once(10.0).chain(repeat(20.0)); 
    let id_assignment_costs = once(10.0).chain(repeat(20.0)); 
    let batch_fixed = once(10.0).chain(repeat(0.0)); 
    let temp: Vec<(usize, &(i32, f32))> = costs.into_iter().enumerate().collect(); 
    temp.sort_by_key(|&(_, &(n, cost))| n); 
    Box::new(temp.into_iter().map(|(i, &(n, cost))| { 
     (
      i, 
      cost + preliminary_examination_costs.next().unwrap() 
       + id_assignment_costs.next().unwrap() + batch_fixed.next().unwrap(), 
     ) 
    })) 
} 

playground

ここでエラーです:

error[E0277]: the trait bound `std::vec::Vec<(usize, &(i32, f32))>: std::iter::FromIterator<(usize, &'a (usize, f32))>` is not satisfied 
    --> src/main.rs:10:73 
    | 
10 |  let temp: Vec<(usize, &(i32, f32))> = costs.into_iter().enumerate().collect(); 
    |                   ^^^^^^^ a collection of type `std::vec::Vec<(usize, &(i32, f32))>` cannot be built from an iterator over elements of type `(usize, &'a (usize, f32))` 
    | 
    = help: the trait `std::iter::FromIterator<(usize, &'a (usize, f32))>` is not implemented for `std::vec::Vec<(usize, &(i32, f32))>` 

error[E0271]: type mismatch resolving `<[[email protected]/main.rs:12:35: 18:6 preliminary_examination_costs:_, id_assignment_costs:_, batch_fixed:_] as std::ops::FnOnce<((usize, &(i32, f32)),)>>::Output == &(i32, f32)` 
    --> src/main.rs:12:5 
    | 
12 |/ Box::new(temp.into_iter().map(|(i, &(n, cost))| { 
13 | |   (
14 | |    i, 
15 | |    cost + preliminary_examination_costs.next().unwrap() 
16 | |     + id_assignment_costs.next().unwrap() + batch_fixed.next().unwrap(), 
17 | |  ) 
18 | |  })) 
    | |_______^ expected tuple, found &(i32, f32) 
    | 
    = note: expected type `(usize, f32)` 
       found type `&(i32, f32)` 
    = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::iter::Map<std::vec::IntoIter<(usize, &(i32, f32))>, [[email protected]/main.rs:12:35: 18:6 preliminary_examination_costs:_, id_assignment_costs:_, batch_fixed:_]>` 
    = note: required for the cast to the object type `std::iter::Iterator<Item=&(i32, f32)>` 
+1

あなたのコードには、あなたが言及しているようなものより多くの問題があります。 'usize'は暗黙的に' i32'に変換されません。さらに、最後に新しいタプルにマップを実行しているので、返されたiterableのアイテムは、もはや ''a'の生涯にバインドされた参照ではいけません。 –

+0

それを見て、あなたは[this](https://play.rust-lang.org/?gist=f20ffa67c1bc814279b53d0dce351545&version=stable)のようなものを探しています。しかし、あなたの問題に合わせたデバッグセッションがなければ、あなたの質問に対処する方法を見つけることができません。スタックオーバーフローの問題としてはほとんど利益はありません。 –

答えて

1

問題が発生したときにはMCVEを作成することは非常に便利です。これはすべての学習者が引き受けることを奨励するものです。

fn foo<'a, I>(costs: I) -> Box<Iterator<Item = &'a i32>> 
where 
    I: IntoIterator<Item = &'a i32>, 
{ 
    Box::new(costs.into_iter().map(|i| i + 1)) 
} 
error[E0271]: type mismatch resolving `<[[email protected]/main.rs:5:36: 5:45] as std::ops::FnOnce<(&'a i32,)>>::Output == &i32` 
--> src/main.rs:5:5 
    | 
5 |  Box::new(costs.into_iter().map(|i| i + 1)) 
    |  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected i32, found &i32 
    | 
    = note: expected type `i32` 
      found type `&i32` 
    = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::iter::Map<<I as std::iter::IntoIterator>::IntoIter, [[email protected]/main.rs:5:36: 5:45]>` 
    = note: required for the cast to the object type `std::iter::Iterator<Item=&i32>` 

あなたは、基準に基づいて、新しい価値を創造し、参照を受け入れている。ここではそのようなMCVEは、あなたのコードを反映しているのです。つまり、戻り値の型はもはや参照ではないので、関数のシグネチャは保持されません。あなたはそれを変更する必要があります。

fn foo<'a, I>(costs: I) -> Box<Iterator<Item = i32>> 

コンパイラはI::IntoIterの具体的な種類について十分に知らないので、これは別のエラーのロックを解除します。

error[E0310]: the associated type `<I as std::iter::IntoIterator>::IntoIter` may not live long enough 
--> src/main.rs:6:5 
    | 
6 |  Box::new(costs.into_iter().map(|i| i + 1)) 
    |  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
    | 
    = help: consider adding an explicit lifetime bound `<I as std::iter::IntoIterator>::IntoIter: 'static`... 
note: ...so that the type `std::iter::Map<<I as std::iter::IntoIterator>::IntoIter, [[email protected]/main.rs:6:36: 6:45]>` will meet its required lifetime bounds 
--> src/main.rs:6:5 
    | 
6 |  Box::new(costs.into_iter().map(|i| i + 1)) 
    |  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 

我々はそれを示唆するようにしてください、そして結合'staticを追加します:また

fn foo<'a, I>(costs: I) -> Box<Iterator<Item = i32>> 
where 
    I: IntoIterator<Item = &'a i32>, 
    I::IntoIter: 'static, 
{ 
    Box::new(costs.into_iter().map(|i| i + 1)) 
} 

参照:


error[E0277]: the trait bound `std::vec::Vec<(usize, &(i32, f32))>: std::iter::FromIterator<(usize, &'a (usize, f32))>` is not satisfied 

あなたが(usize, &'a (usize, f32))のイテレータを持っていて、(usize, &(i32, f32))にそれらをしようとしているため、このエラーがあります。このようなタイプは変換できません。

+0

MVCEに還元することの問題は、私がいつも正しい方法でそれを行うことができないということです。例えば、私は 'foo'関数を多少変更しましたが、まだ問題があります。 https://play.rust-lang.org/?gist=b2bef2a57f76aae6c70eb0e28f4db44f&version=stable。代わりに私の質問に答えることができますか? – user1685095

+0

私はペアのコンテナ '(u32、f32)'を受け取ります。あなたは、私が新しい価値を創造しているからです(それはどういう意味ですか、正確に言えば、私はもう参照を返していません)。反復子を '(u32、f32)'の組に戻したい。私が知っている限り、rustはヒープ上にペアを割り当てて参照(ポインタ)を返すことができます。私はあなたのコメントのいずれかを完全に理解していない、あなたは詳細を詳述できますか?私は本の最初の部分からの生涯に心地よいと感じますが、私はそのアイデアを理解していますが、一般的な生涯と特性に関しては、錆が私にはぎこちなくなります。 – user1685095

+0

私は錆にどのように言いたいのか分かりませんし、私が望んでいることを理解できません。 – user1685095

関連する問題