-
-
Save rust-play/322e7b57f612de68a76bf2b6107d60f9 to your computer and use it in GitHub Desktop.
Code shared from the Rust Playground
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::collections::HashMap; | |
// use std::rc::Rc; | |
// use std::cell::{RefCell, RefMut}; | |
fn main() { | |
// This code simulates an insert() function. | |
let mut m = M { children: HashMap::new() }; | |
let mut mb = M { children: HashMap::new() }; | |
let mut mc: M = M { children: HashMap::new() }; | |
let mut md: M = M { children: HashMap::new() }; | |
let me: M = M { children: HashMap::new() }; | |
md.children.insert("weld".to_string(), me); | |
mc.children.insert("nut".to_string(), md); | |
mb.children.insert("washer".to_string(), mc); | |
m.children.insert("bolt".to_string(), mb); | |
//////// | |
// Prove to ourselves that the normal find() function works. | |
let a_success = m.find(vec!["bolt", "washer", "nut"]); | |
match a_success { | |
Ok(child) => println!("Successful success: {:?}", child), | |
Err(msg) => println!("Failed success: {}", msg) | |
} | |
let another_success = m.find(vec!["bolt", "washer", "nut", "weld"]); | |
match another_success { | |
Ok(child) => println!("Successful success: {:?}", child), | |
Err(msg) => println!("Failed success: {}", msg) | |
} | |
let a_failure = m.find(vec!["nut", "washer", "bolt"]); | |
match a_failure { | |
Ok(child) => println!("Failed failure: {:?}", child), | |
Err(msg) => println!("Successful failure: {}", msg) | |
} | |
let another_failure = m.find(vec!["weld"]); | |
match another_failure { | |
Ok(child) => println!("Failed failure: {:?}", child), | |
Err(msg) => println!("Successful failure: {}", msg) | |
} | |
// Desired usage pseudocode | |
// let mut m = M { children: HashMap::new() } | |
// m.insert(vec!["bolt", "washer"]); | |
// let blah = m.find_with_path(vec!["bolt", "washer"]); | |
// let new_m = blah.last(); // Washer M | |
// new_m.insert(vec!["nut", "weld"]); | |
// new_m.find(vec!["nut", "weld"]); | |
// m.find(vec!["bolt", "washer", "nut", "weld"]); | |
// Yay | |
// let another_m = blah[0]; // Bolt M | |
// another_m.find(vec!["washer"]) | |
// Yay | |
// Profit | |
} | |
#[derive(Debug)] | |
struct M { | |
children: HashMap<String, M> | |
} | |
impl M { | |
fn find(&mut self, key: Vec<&str>) -> Result<&mut M, String> { | |
let mut current = Some(self); | |
for key_part in key[..].to_vec() { | |
match current.and_then(|item| item.children.get_mut(key_part)) { | |
Some(child) => current = Some(child), | |
None => current = None | |
} | |
} | |
match current { | |
Some(child) => Ok(child), | |
None => Err(format!("Unable to locate key [{}]", key.join(", "))) | |
} | |
} | |
fn find_with_path(&mut self, key: Vec<&str>) /* -> Some list of Ms */ { | |
let mut current = Some(self); | |
// let path: Vec<something> = Vec::new() | |
// ^^ Some structure to hold references to | |
// each M we successfully find, to be | |
// returned to caller | |
for key_part in key[..].to_vec() { | |
match current.and_then(|item| item.children.get_mut(key_part)) { | |
Some(child) => { | |
// Similar to other find function, but every time we | |
// successfully find another child M, we push it | |
// onto a list of some kind that can be returned to | |
// the caller. We then move onto the child and the | |
// next piece of the key, as in the other find | |
// function. | |
// | |
// Magic goes here. Somehow store reference in a | |
// list or other structure that will allow me to | |
// return a group of Ms or references to Ms to | |
// the caller. The caller must be able to get | |
// his hands on mutable versions of the Ms so | |
// as to call additional methods on them. | |
// | |
// I've tried various approaches. For a minute, | |
// I thought Rc/RefCell might save me, but I | |
// couldn't figure out how to store | |
// Rc<RefCell<&M>>s from current or child, | |
// because those belong to this function and/or | |
// this match arm. | |
current = Some(child) | |
}, | |
None => current = None | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment