Tôi đang cố gắng triển khai một cái gì đó như dây kéo nhưng lợi dụng các tham chiếu có thể thay đổi để tránh phải cấu trúc lại và cấu trúc lại dữ liệu khi tôi di chuyển nó. Tôi đã có mã ví dụ cho một nỗ lực với một danh sách liên kết, mặc dù tôi lý tưởng muốn áp dụng nó cho các cấu trúc khác, như cây cối.Lưu tham chiếu có thể thay đổi cho sau này ngay cả khi được đặt tên
pub enum List<T> {
Empty,
Cons { head: T, tail: Box<List<T>> },
}
pub struct Zipper<'a, T: 'a> {
trail: Option<Box<Zipper<'a, T>>>,
focus: &'a mut List<T>,
}
impl<'a, T: 'a> Zipper<'a, T> {
pub fn down(&'a mut self) {
match self.focus {
&mut List::Empty =>(),
&mut List::Cons {
tail: ref mut xs, ..
} => {
//We need a way to convince rust that we won't use oldZipper
//until xs goes out of scope
let oldZipper = std::mem::replace(
self,
Zipper {
trail: None,
focus: xs,
},
);
self.trail = Some(Box::new(oldZipper));
}
}
}
}
Trình kiểm tra mượn là không hài lòng với điều này:
error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> src/main.rs:21:21
|
16 | tail: ref mut xs, ..
| ---------- first mutable borrow occurs here
...
21 | self,
| ^^^^ second mutable borrow occurs here
...
30 | }
| - first borrow ends here
Đây không phải là đáng ngạc nhiên: nếu chúng ta có một dây kéo tập trung vào một danh sách và gọi down
vào nó, chúng tôi nhận dây kéo với một mutable tham chiếu đến đuôi của danh sách đó, vì vậy chúng tôi có bí danh có thể thay đổi được.
Tuy nhiên, nếu chúng tôi không bao giờ sử dụng số trail
của Zipper trước khi focus
vượt quá phạm vi, chúng tôi sẽ không bao giờ có thể "xem" bí danh có thể thay đổi được. Điều này có vẻ tương tự như khoản vay có thể thay đổi thông thường: bạn không thể sử dụng biến số mà bạn đã vay từ khi khoản vay vượt quá phạm vi.
Có cách nào để giải thích điều này cho người kiểm tra vay không? Nếu bạn muốn "giải thích" cho người mượn mượn vay hai lát không chồng lên nhau từ một mảng thì không sao, bạn có thể sử dụng split_at
: có một số chức năng tương ứng sẽ thực thi trail
không bao giờ được sử dụng trước focus
không nằm ngoài phạm vi và làm như vậy, thỏa mãn người mượn tiền?
Điều này [thực hiện một dây kéo] (https://stackoverflow.com/a/36168919/155423) trả lời câu hỏi của bạn? – Shepmaster
Không thực sự. Thực hiện một dây kéo kiểu haskell, giống như cái mà bạn liên kết, có vẻ tương đối đơn giản. Tôi đang cố gắng, ngoài ra, tránh tháo cấu trúc dữ liệu khi bạn hạ xuống, và do đó cần phải lắp ráp lại nó khi bạn lên. – user1454156
Tôi đoán các ví dụ về câu trả lời tôi muốn là: "Phân tích của bạn không chính xác: nếu bạn sử dụng mã không an toàn để thực hiện điều này, nó sẽ dẫn đến UB. Đây là lý do", "Phân tích của bạn là chính xác, nhưng không thể thuyết phục người mượn tiền, ngay cả khi sử dụng máy tính tiền không an toàn ", " Phân tích của bạn là chính xác, nhưng AFAIK không ai viết mã không an toàn trong thư viện tốt cho bạn ", hoặc " Phân tích của bạn là chính xác, đây là thư viện bạn muốn " – user1454156