use std::sync::Arc; use crate::interpreter::{self, Interpreter, Value}; pub fn pair(interpreter: &mut Interpreter, args: &[Arc]) -> Arc { let keys = interpreter .eval(args[0].clone()) .list() .expect("a list of keys"); let vals = interpreter .eval(args[1].clone()) .list() .expect("a list of values"); let pairs = keys .into_iter() .zip(vals) .map(|(key, value)| Arc::new(Value::Pair(key, value))) .collect::>(); interpreter::vec_to_value(&pairs) } fn assoc_inner(key: Arc, pairs: &[Arc]) -> Option> { let get_value = |pair: &Arc| { if let Value::Pair(k, v) = &**pair { (k == &key).then(|| v.clone()) } else { None } }; pairs.iter().filter_map(get_value).next() } pub fn assoc(interpreter: &mut Interpreter, args: &[Arc]) -> Arc { let key = interpreter.eval(args[0].clone()); let pairs = interpreter.eval(args[1].clone()).list().expect("a list"); assoc_inner(key, &pairs).unwrap() } pub fn sublis(interpreter: &mut Interpreter, args: &[Arc]) -> Arc { fn sublis_inner(expression: Arc, replacements: &[Arc]) -> Arc { if let Some(value) = assoc_inner(expression.clone(), replacements) { return value.clone(); } if let Value::Pair(a, b) = &*expression { return Arc::new(Value::Pair( sublis_inner(a.clone(), replacements), sublis_inner(b.clone(), replacements), )); } expression } let expression = interpreter.eval(args[1].clone()); let replacements = interpreter .eval(args[0].clone()) .list() .expect("a list of replacements"); sublis_inner(expression, &replacements) }