use mumu::parser::types::{FunctionValue, Value};
use mumu::parser::interpreter::{Interpreter, apply_n_ary_function_value};
use super::common::{is_placeholder, make_two_arg_partial};
pub fn array_partition_bridge(interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
match args.len() {
2 => {
let pred_fn = &args[0];
let arr = &args[1];
let pred_pl = is_placeholder(pred_fn);
let arr_pl = is_placeholder(arr);
if !pred_pl && !arr_pl {
do_partition(interp, pred_fn.clone(), arr.clone())
} else {
Ok(make_two_arg_partial(
do_partition,
if pred_pl { None } else { Some(pred_fn.clone()) },
if arr_pl { None } else { Some(arr.clone()) },
"array-transform-partition-partial"
))
}
}
1 => Ok(make_two_arg_partial(do_partition, Some(args[0].clone()), None, "array-transform-partition-partial")),
0 => Ok(make_two_arg_partial(do_partition, None, None, "array-transform-partition-partial")),
n => Err(format!("array:partition => expects 2 arguments (fn, array), got {}", n)),
}
}
fn do_partition(
interp: &mut Interpreter,
pred_fn: Value,
arr_val: Value,
) -> Result<Value, String> {
let pred_fn = match pred_fn {
Value::Function(f) => f,
other => return Err(format!("array:partition => first argument must be a function, got {:?}", other)),
};
let items = match arr_val {
Value::IntArray(xs) => xs.iter().map(|&x| Value::Int(x)).collect(),
Value::FloatArray(xs) => xs.iter().map(|&x| Value::Float(x)).collect(),
Value::StrArray(xs) => xs.iter().map(|x| Value::SingleString(x.clone())).collect(),
Value::BoolArray(xs) => xs.iter().map(|&x| Value::Bool(x)).collect(),
Value::MixedArray(xs) => xs,
other => return Err(format!("array:partition => unsupported array type: {:?}", other)),
};
let mut yes = Vec::new();
let mut no = Vec::new();
for v in items {
let res = apply_n_ary_function_value(interp, pred_fn.clone(), vec![v.clone()]);
match res {
Ok(Value::Bool(true)) => yes.push(v),
Ok(Value::Bool(false)) => no.push(v),
_ => no.push(v),
}
}
Ok(Value::MixedArray(vec![Value::MixedArray(yes), Value::MixedArray(no)]))
}