同じタイプのベクトルを圧縮すると、マップクロージャー内で異なるタイプになります
バックグラウンド
列挙型バリアント型(コピー不可)が与えられた場合:
enum AstNode {
Op(Func, Box<AstNode>, Box<AstNode>),
Val(f64),
// others...
}
このような2つのベクトルに対して操作を実行しようとしています。
fn apply_func_iterative(func: Func, lhs: Vec<AstNode>, rhs: Vec<AstNode>) -> Vec<AstNode> {
lhs.iter().zip(rhs).map(|(&l,r)| apply_func(func,l,r)).collect() // l and r are declared differently!
}
fn apply_func(func: Func, lhs: AstNode, rhs: AstNode) -> AstNode {
// magic happens here!
}
クロージャ内で、lhs
要素タイプを想定l: &AstNode
zip形式一方rhs
の要素タイプを取りますl: AstNode
。(クロージャータプルの異なる宣言に注意してください)。
質問
なぜそうなのですか?
ベクトルの要素を参照ではなく値で反復する方法はありますか?これは、zip形式の要素の観察された動作から可能であるように思われます。
(この例では、この違いにより構文宣言が少し奇妙になりますが、実際には、参照変数を関数に渡すときにボローチェッカーにぶつかりました)
免責事項:私はRustにかなり慣れていません
回答
このIterator::zip方法は特別なことは何もしていません。単に両方のイテレータを組み合わせているだけです。しばらくすると(vs non- )になることがlhs.iter()
わかります。Iterator<&AstNode>
rhs
Iterator<AstNode>
&
&
ベクトルの要素を参照ではなく値で反復する方法はありますか?これは、zip形式の要素の観察された動作から可能であるように思われます。
はい、この動作を制御する方法があります。重要なのは、zip()
の引数rhs
がIntoIterator
特性を実装する必要があることに注意することです。内部的にzip()
はrhs.into_iter()
、そこからイテレータを取得するために呼び出します。従来の動作ではということである.iter()だけ借りソース従ってのみ、その値への参照を提供することができます。一方で消費または「所有権のかかる」ソースと所有値を得ることができます。.into_iter()
これらを組み合わせて、lhs.into_iter().zip(rhs)
値に対してイテレータを取得する(AstNode, AstNode)
かlhs.iter().zip(rhs.iter())
、参照に対してイテレータを取得するために使用できます(&AstNode, &AstNode)
。