Hi, I'm new to rust and wasn't able to successfully solve this error by myself.
Playground: Rust Playground
I'm not sure if the code is correct as it's an attempt to shrink down the actual code to a minimal reproducible example. It should suffice to illustrate the problem though.
use std::collections::HashMap;
enum Value<'a> {
Null,
Symbol(&'a str),
Number(&'a i32),
Cons {
car: &'a Value<'a>,
cdr: Option<&'a Value<'a>>,
},
}
#[derive(Clone)]
enum V<'a> {
Null,
Number(&'a i32),
String(&'a str),
Symbol(&'a str),
Builtin(fn(Vec<V>, &'a S) -> V<'a>),
Function(Vec<&'a str>, &'a Value<'a>),
}
struct S<'a> {
i: HashMap<&'a str, V<'a>>,
parent: Option<&'a S<'a>>,
}
struct ConsItr<'a> {
cur: Option<&'a Value<'a>>,
}
impl<'a> Iterator for ConsItr<'a> {
type Item = &'a Value<'a>;
fn next(&mut self) -> Option<Self::Item> {
match self.cur {
Some(v) => match v {
Value::Cons { car, cdr } => {
let next = car;
self.cur = match cdr {
Some(v) => Some(v),
None => None,
};
Some(next)
},
_ => None,
},
_ => None,
}
}
}
fn apply<'a>(body: &'a Value, scope: &'a S<'a>) -> V<'a> {
let body_itr = ConsItr { cur: Some(body) };
let mut ret = V::Null;
for val in body_itr {
ret = eval(&val, scope);
}
ret
}
fn eval<'a>(val: &'a Value, s: &'a S<'a>) -> V<'a> {
match val {
Value::Number(n) => V::Number(n),
Value::Symbol(str) => V::Symbol(str),
Value::Cons { car, cdr: _ } => {
let car = eval(car, s);
match car {
V::Function(_params, body) => {
let new_scope = S {
i: HashMap::new(),
parent: Some(s),
};
// code elided...
apply(body, &new_scope)
}
_ => V::Null,
}
}
_ => V::Null,
}
}
fn main() {
let m = S {
i: HashMap::new(),
parent: None,
};
let v = Value::Cons {
car: &Value::Symbol("lambda"),
cdr: Some(&Value::Cons {
car: &Value::Cons {
car: &Value::Null,
cdr: None,
},
cdr: Some(&Value::Cons {
car: &Value::Number(&1),
cdr: None,
}),
}),
};
eval(&v, &m);
}
The error I'm getting is:
error[E0515]: cannot return value referencing local variable `new_scope`
--> src/main.rs:74:21
|
74 | apply(body, &new_scope)
| ^^^^^^^^^^^^----------^
| | |
| | `new_scope` is borrowed here
| returns a value referencing data owned by the current function
Any help is appreciated.