I’m trying to implement a trie in rust to learn the language, especially around recursive structures. In the process, I"m seeing that the add_word method gives me an error. The implementation is
use std::array;
#[derive(Default)]
pub struct Trie {
is_end: bool,
pub children: [Option<Box<Trie>>; 26],
}
impl Trie {
pub fn new() -> Box<Self> {
Box::new(Trie {
is_end: false,
children: array::from_fn(|_| None),
})
}
pub fn starts_with(&self, s: &str) -> bool {
if s.is_empty() {
return true;
}
let child = &self.children[(s.as_bytes()[0] - b'a') as usize];
if child.is_none() {
return false;
}
child
.as_ref()
.unwrap()
.starts_with(s.get(1..).unwrap_or_default())
}
pub fn add_word(&mut self, s: &str) {
if s.is_empty() {
self.is_end = true;
}
let index = (s.as_bytes()[0] - b'a') as usize;
let child = &self.children[index];
if child.is_none() {
return;
}
child
.as_ref()
.unwrap()
.add_word(s.get(1..).unwrap_or_default());
}
}
and the error is cannot borrow data in a & reference as mutable cannot borrow as mutable. I’m open to other fixes not directly related to my question that may yield more idiomatic rust code. Like, I believe I could have used unwrap_or_default in places but my attempts led to a bunch of other scary errors that didn’t get easily resolved by following clippy’s advice.
>Solution :
Try This:
use std::array;
#[derive(Default)]
pub struct Trie {
is_end: bool,
pub children: Vec<Option<Box<Trie>>>,
}
impl Trie {
pub fn new() -> Box<Self> {
Box::new(Trie {
is_end: false,
children: vec![None; 26],
})
}
pub fn starts_with(&self, s: &str) -> bool {
if s.is_empty() {
return true;
}
let child = &self.children[(s.as_bytes()[0] - b'a') as usize];
if child.is_none() {
return false;
}
child
.as_ref()
.unwrap()
.starts_with(s.get(1..).unwrap_or_default())
}
pub fn add_word(&mut self, s: &str) {
if s.is_empty() {
self.is_end = true;
} else {
let index = (s.as_bytes()[0] - b'a') as usize;
let child = self.children.get_mut(index).unwrap();
if child.is_none() {
*child = Some(Trie::new());
}
child.as_mut().unwrap().add_word(s.get(1..).unwrap_or_default());
}
}
}