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 đồ
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 lhs
phần tử giả định kiểu l: &AstNode
trong khi các rhs
phầ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
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 rhs
mang 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ố rhs
phả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)
.