2015-05-26 17 views
31

Tôi đang cố gắng viết một chương trình liên quan đến việc lọc và xếp chồng lên các mảng. Tôi đã sử dụng The Rust Programming Language, first edition làm tài liệu tham khảo, nhưng tôi không hiểu điều gì sẽ xảy ra khi tôi tạo vòng lặp qua mảng. Dưới đây là một ví dụ:Làm cách nào để lặp qua một mảng?

fn compiles() { 
    let range = (1..6); 
    let range_iter = range.into_iter(); 
    range_iter.filter(|&x| x == 2); 
} 

fn does_not_compile() { 
    let array = [1, 4, 3, 2, 2]; 
    let array_iter = array.into_iter(); 
    //13:34 error: the trait `core::cmp::PartialEq<_>` is not implemented for the type `&_` [E0277] 
    array_iter.filter(|&x| x == 2); 
} 

fn janky_workaround() { 
    let array = [1, 4, 3, 2, 2]; 
    let array_iter = array.into_iter(); 
    // Note the dereference in the lambda body 
    array_iter.filter(|&x| *x == 2); 
} 

(Rust playground)

Trong chức năng đầu tiên, tôi làm theo mà các iterator trên phạm vi không mất quyền sở hữu, vì vậy tôi phải mất một &x trong lambda filter 's, nhưng Tôi không hiểu tại sao ví dụ thứ hai với mảng hoạt động khác nhau.

Trả lời

25

Trong trường hợp như thế này, nó rất hữu ích để buộc trình biên dịch cho bạn biết loại biến. Hãy kích hoạt một lỗi loại bằng cách gán đối số đóng cửa để một kiểu không tương thích:

array_iter.filter(|x| { let() = x; true }); 

này không thành công với:

error[E0308]: mismatched types 
    --> src/main.rs:12:33 
    | 
12 |  array_iter.filter(|x| { let() = x; true }); 
    |         ^^ expected &&{integer}, found() 
    | 
    = note: expected type `&&{integer}` 
       found type `()` 

Bây giờ chúng ta biết loại x là một &&{integer} - một tham chiếu đến một tham chiếu đến một số số loại số nguyên. Khi đó, chúng tôi có thể đối sánh với điều đó thay vì:

fn hooray() { 
    let array = [1, 4, 3, 2, 2]; 
    let array_iter = array.into_iter(); 
    array_iter.filter(|&&x| x == 2); 
} 

Câu hỏi bây giờ trở thành "tại sao tham chiếu đến tham chiếu"? Phiên bản ngắn là iterator of an array returns references (xem phần type Item = &'a T). Ngoài ra, Iterator::filter passes a reference để đóng cửa để ngăn di chuyển và sau đó mất các loại không phải Copy.

+1

Cảm ơn bạn! Tôi đã chọn câu trả lời này bởi vì nó hướng dẫn tôi qua cách tôi có thể đã sử dụng trình biên dịch để tự mình tìm ra nó. Tôi cũng đánh giá cao các liên kết để tìm hiểu thêm. – WillEngler

19

Mảng là loại [T; N] trong Rust, cho bất kỳ loại phần tử nào T và số không đổi N. Đó là một mảng kích thước cố định.

Rust không triển khai trình lặp vòng lặp giá trị cho mảng tại thời điểm này. Tất cả các mảng coerce để slice (loại [T]) và các phương thức slice có sẵn trên mảng vì điều này. Các mảng cũng nhận được trình lặp của slice, được gọi là std::slice::Iter<'a, T> và có các phần tử kiểu &'a T: nó lặp lại theo tham chiếu!

Đây là lý do tại sao into_iter() trên Range<i32> tạo ra một iterator của i32into_iter() trên [i32; 5] tạo ra một iterator của &i32.

Nếu bạn cần bởi bộ lặp giá trị cho mảng, chúng đã được triển khai trong hệ sinh thái rộng hơn, xem (1)(2).

0

Như Shepmaster và bluss nói, bạn có thể kiểm tra documentation for the array type, mà đề cập đến:

Mảng các kích cỡ 0-32 (bao gồm) thực hiện đặc điểm sau đây nếu loại yếu tố cho phép nó:

  • IntoIterator (thực hiện cho &[T; N]&mut [T; N])

Như đã nói, đây chỉ là tài liệu tham khảo và được phản ánh theo loại Item: type Item = &'a Ttype Item = &'a mut T.

Các vấn đề liên quan