Membuat zip vektor dengan tipe yang sama menghasilkan tipe yang berbeda dalam penutupan peta

Aug 16 2020

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, lhselemen mengambil tipe l: &AstNodesedangkan rhselemen 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

6 kmdreko Aug 16 2020 at 04:55

The Iterator::zipMetode tidak melakukan sesuatu yang istimewa, itu hanya menggabungkan kedua iterator. Anda menemukan bahwa lhs.iter()menghasilkan Iterator<&AstNode>sementara rhsmenghasilkan 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 rhsharus mengimplementasikan IntoIteratorsifat 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).