Membuat zip vektor dengan tipe yang sama menghasilkan tipe yang berbeda dalam penutupan peta
Latar Belakang
Dengan jenis varian enum (tidak dapat disalin):
enum AstNode {
Op(Func, Box<AstNode>, Box<AstNode>),
Val(f64),
// others...
}
Mencoba menjalankan operasi pada dua vektor seperti itu:
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!
}
Dalam closure, lhs
elemen mengambil tipe l: &AstNode
sedangkan rhs
elemen zip mengambil tipe l: AstNode
. (Perhatikan deklarasi berbeda di closure tuple).
Pertanyaan
Mengapa demikian?
Apakah ada cara untuk mengulang elemen vektor dengan nilai alih-alih dengan referensi? Tampaknya hal ini dimungkinkan dari perilaku elemen zip yang diamati.
(Dalam contoh ini, perbedaan ini menghasilkan sedikit keanehan dalam deklarasi sintaks, tetapi dalam praktiknya, saya telah melawan pemeriksa peminjam ketika meneruskan variabel referensi ke dalam suatu fungsi)
Penafian: Saya cukup baru mengenal Rust
Jawaban
The Iterator::zipMetode tidak melakukan sesuatu yang istimewa, itu hanya menggabungkan kedua iterator. Anda menemukan bahwa lhs.iter()
menghasilkan Iterator<&AstNode>
sementara rhs
menghasilkan Iterator<AstNode>
( &
vs non- &
).
Apakah ada cara untuk mengulang elemen vektor dengan nilai alih-alih dengan referensi? Tampaknya hal ini dimungkinkan dari perilaku elemen zip yang diamati.
Ya, ada cara untuk mengontrol perilaku ini. Kuncinya adalah untuk memperhatikan bahwa zip()
argumen rhs
harus mengimplementasikan IntoIterator
sifat tersebut. Interally, zip()
akan memanggil rhs.into_iter()
untuk mendapatkan iterator darinya. Perilaku konvensional yang .iter()hanya meminjam sumber dan oleh karena itu hanya dapat memberikan referensi nilai-nilainya. Sementara mengkonsumsi atau "mengambil kepemilikan" sumber dan dapat menghasilkan nilai yang dimiliki..into_iter()
Menggabungkannya, Anda dapat melakukannya lhs.into_iter().zip(rhs)
untuk mendapatkan iterator di atas nilai (AstNode, AstNode)
atau gunakan lhs.iter().zip(rhs.iter())
untuk mendapatkan iterator di atas referensi (&AstNode, &AstNode)
.