Việc nén các vectơ cùng loại dẫn đến các loại khác nhau trong việc đóng bản đồ

Aug 16 2020

Lý lịch

Cho một loại biến thể enum (không thể sao chép):

enum AstNode {
  Op(Func, Box<AstNode>, Box<AstNode>),
  Val(f64),
  // others...
}

Cố gắng chạy một hoạt động trên hai vectơ như vậy:

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!
}

Trong bao đóng, các lhsphần tử giả định kiểu l: &AstNodetrong khi các rhsphần tử nén có kiểu l: AstNode. (Lưu ý các khai báo khác nhau trong bộ đóng cửa).

Câu hỏi

Tại sao điều này là trường hợp?

Có cách nào để lặp lại các phần tử của véc tơ theo giá trị thay vì tham chiếu không? Có vẻ như điều này có thể thực hiện được từ hành vi quan sát được của các phần tử được nén.

(Trong ví dụ này, sự khác biệt này dẫn đến một chút kỳ lạ trong khai báo cú pháp, nhưng trong thực tế, tôi đã đánh bại trình kiểm tra mượn khi chuyển biến tham chiếu vào một hàm)

Tuyên bố từ chối trách nhiệm: Tôi còn khá mới đối với Rust

Trả lời

6 kmdreko Aug 16 2020 at 04:55

Các Iterator::zipphương pháp không làm bất cứ điều gì đặc biệt, nó chỉ đơn giản là kết hợp cả hai vòng lặp. Bạn đang thấy rằng kết lhs.iter()quả Iterator<&AstNode>trong một thời gian rhsmang lại Iterator<AstNode>( &so với không &).

Có cách nào để lặp lại các phần tử của véc tơ theo giá trị thay vì tham chiếu không? Có vẻ như điều này có thể thực hiện được từ hành vi quan sát được của các phần tử được nén.

Có, có một cách để kiểm soát hành vi này. Điều quan trọng là lưu ý rằng zip()đối số rhsphải triển khai IntoIteratorđặc điểm. Nói một cách tổng thể, zip()sẽ gọi rhs.into_iter()để lấy một trình lặp từ nó. Hành vi thông thường là .iter()chỉ mượn nguồn và do đó chỉ có thể cung cấp các tham chiếu đến các giá trị của nó. Trong khi tiêu thụ hoặc "sở hữu" nguồn và có thể mang lại các giá trị được sở hữu..into_iter()

Kết hợp những thứ đó, bạn có thể làm lhs.into_iter().zip(rhs)để lấy một trình lặp qua các giá trị (AstNode, AstNode)hoặc sử dụng lhs.iter().zip(rhs.iter())để lấy một trình lặp qua các tham chiếu (&AstNode, &AstNode).