1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
use crate::function::OptionalArg; use crate::obj::objiter; use crate::obj::objtype; use crate::pyobject::{PyObjectRef, PyResult}; use crate::vm::VirtualMachine; pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { let ctx = &vm.ctx; py_module!(vm, "_functools", { "reduce" => ctx.new_function(functools_reduce), }) } fn functools_reduce( function: PyObjectRef, sequence: PyObjectRef, start_value: OptionalArg<PyObjectRef>, vm: &VirtualMachine, ) -> PyResult { let iterator = objiter::get_iter(vm, &sequence)?; let start_value = if let OptionalArg::Present(val) = start_value { val } else { objiter::call_next(vm, &iterator).map_err(|err| { if objtype::isinstance(&err, &vm.ctx.exceptions.stop_iteration) { let exc_type = vm.ctx.exceptions.type_error.clone(); vm.new_exception_msg( exc_type, "reduce() of empty sequence with no initial value".to_owned(), ) } else { err } })? }; let mut accumulator = start_value; while let Ok(next_obj) = objiter::call_next(vm, &iterator) { accumulator = vm.invoke(&function, vec![accumulator, next_obj])? } Ok(accumulator) }