지퍼처럼 구현하려고하지만 변경 가능한 참조를 활용하여 데이터 구조를 분해하고 재구성하지 않아도됩니다. 연결된 목록을 사용하기위한 예제 코드가 있지만, 나무와 같은 다른 구조에 적용하는 것이 이상적입니다.에일리어스가 적용된 후에도 변경 가능한 참조 저장
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));
}
}
}
}
차용 검사기이 함께 행복하지 않다 :
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
이것은 놀라운 일이 아니다 : 우리는 지퍼가리스트에 초점을 맞추고 그것에 down
를 호출 할 경우, 우리는 변경 가능한 지퍼를 얻을 수 그 목록의 꼬리를 참조하십시오. 그래서 우리는 앨리어스를 변경할 수 있습니다.
그러나 지퍼의 trail
을 사용하지 않고 focus
이 범위를 벗어나지 않으면 변경 가능한 앨리어싱을 "볼"수 없습니다. 이것은 정상적인 변경 가능한 차용과 유사합니다. 차용이 범위를 벗어날 때까지 빌린 변수를 사용할 수 없습니다.
차용 검사기에 설명 할 수있는 방법이 있습니까? 배열에서 두 개의 겹쳐지지 않는 조각을 빌려 오는 것이 차용 검사기에 "설명"하고 싶다면 split_at
을 사용할 수 있습니다. trail
이 사용되지 않는 일부 기능이 있습니까? focus
이 범위를 벗어나고 이렇게하면 빌려가는 사람을 만족시킬 수 있습니까?
[지퍼 구현] (https://stackoverflow.com/a/36168919/155423)이 질문에 대한 답변을 제공합니까? – Shepmaster
아닙니다. 연결 한 것과 같은 haskell 스타일의 지퍼를 구현하는 것은 비교적 간단합니다. 나는 또한 당신이 내려갈 때 데이터 구조를 분해하는 것을 피하려고 노력하고있다. 따라서 당신이 상승 할 때 그것을 재구성 할 필요가있다. – user1454156
대답의 예는 다음과 같습니다. "분석이 잘못되었습니다 : 안전하지 않은 코드를 사용하여 이것을 구현하면 UB가됩니다.", "분석은 정확하지만 불가능합니다. "귀하의 분석은 정확하지만 AFAIK는 훌륭한 도서관의 안전하지 않은 코드를 작성했습니다."또는 "귀하의 분석은 정확합니다. 여기 도서관은 – user1454156