rustl-systems

Assembling a string and returning it with lifetime parameters for a l-system


I'm trying to implement a L-System struct and am struggling with it. I already tried different approaches but my main struggle comes from lifetime of references. What I'm trying to achieve is passing the value of the applied axioms back to my system variable, which i passed with the necessary lifetime in apply_axioms_once.

use std::collections::HashMap;

struct LSytem<'a> {
    axioms: HashMap<&'a char, &'a str>,
}

impl<'a> LSytem<'a> {

    fn apply_axioms_once(&mut self, system: &'a mut str) -> &'a str {
        let mut applied: String = String::new();

        for c in system.chars() {
            let axiom = self.axioms.get(&c).unwrap();

            for s in axiom.chars() {
                applied.push(s);
            }
        }
        system = applied.as_str();
        system 
    }

    fn apply_axioms(&mut self, system: &'a str, iterations: u8) -> &'a str {
        let mut applied: &str = system;

        // check for 0?
        for _ in 0..iterations {
            applied = self.apply_axioms_once(applied);
        }
        &applied
    }
}

I already read a couple of similar questions, but still can't quite wrap my head around it. What seems to be the most on point answer is https://stackoverflow.com/a/42506211/18422275, but I'm still puzzled about how to apply this to my issue.

I am still a beginner in rust, and way more bloody than i thought.


Solution

  • This can't work because you return a reference of a data created inside the function (so the given data has a lifetime until the end of the function scope, the returned reference would point to nothing).

    You shoud try to return String from your functions instead, so the returned data can be owned.

    I made this example to try out:

    use std::collections::HashMap;
    
    struct LSytem<'a> {
        axioms: HashMap<&'a char, &'a str>,
    }
    
    impl<'a> LSytem<'a> {
    
        fn apply_axioms_once(&mut self, system: &String) -> String {
            let mut applied: String = String::new();
    
            for c in system.chars() {
                let axiom = self.axioms.get(&c).unwrap();
    
                for s in axiom.chars() {
                    applied.push(s);
                }
            }
    
            applied 
        }
    
        fn apply_axioms(&mut self, system: &String, iterations: u8) ->String{
            let mut applied = String::from(system);
    
            // check for 0?
            for _ in 0..iterations {
                applied = self.apply_axioms_once(system);
            }
            applied
        }
    }
    
    fn main() {
        let mut ls = LSytem {axioms: HashMap::new()};
        ls.axioms.insert(&'a', "abc");
        let s = String::from("a");
        ls.apply_axioms(&s,1);
    }