danield9tqh
danield9tqh

Reputation: 71

Returning a constructed recursive data structure in Rust

I've just started learning Rust and am coming from a functional programming background. I'm trying to create a parser in rust and have defined this recursive data structure

enum SimpleExpression<'a> {
    Number(u64),
    FunctionCall(Function, &'a SimpleExpression<'a>, &'a SimpleExpression<'a>)
}

I initially had defined it as

enum SimpleExpression {
    Number(u64),
    FunctionCall(Function, SimpleExpression, SimpleExpression)
}

but got a complaint from the compiler saying this type had an infinite size. I'm not used to having to worry about managing memory so this confused me for a second but now it makes a lot of sense. Rust cannot allocate memory for a data structure where the size is not defined. So changing the SimpleExpression to &'a SimpleExpression<'a> makes sense.

The second problem I came across was when implementing the parsing function (excuse the verboseness)

fn parse_simple_expr(input: &str) -> Option<(SimpleExpression, usize)> {
    match parse_simple_expr(&input) {
        Some((left, consumed1)) => match parse_function_with_whitespace(&input[consumed1..]) {
            Some((func, consumed2)) => match parse_simple_expr(&input[consumed1+consumed2..]) {
                Some((right, consumed3)) => Some((
                    SimpleExpression::FunctionCall(func, &left.clone(), &right.clone()),
                    consumed1 + consumed2 + consumed3
                )),
                None => None
            },
            None => None
        },
        None => None
    }
}

But basically what is wrong with this function is I am creating SimpleExpression objects inside the function and then trying to return references to them from the function. The problem here of course is that the objects will be dropped when the function returns and Rust does not allow dangling references so I get the error cannot return value referencing temporary value on &left.clone() and &right.clone().

It makes sense to me why this does not work but I am wondering if there is another way to execute this pattern to be able to create a recursive object and return it from a function. Or is there some fundamental reason this will never work in which case are there any good alternatives? Since my code is confusing I've also provided a simpler example of a recursive structure but that has the same limitations in case that helps to better understand the issue.

enum List<'a> {
    End,
    Next((char, &'a List<'a>))
}

fn create_linked(input: &str) -> List {
    match input.chars().next() {
        Some(c) => List::Next((c, &create_linked(&input[1..]))),
        None => List::End
    }
}

Upvotes: 0

Views: 358

Answers (0)

Related Questions