(args: ReduceArgs, vm: &VirtualMachine)
| 26 | |
| 27 | #[pyfunction] |
| 28 | fn reduce(args: ReduceArgs, vm: &VirtualMachine) -> PyResult { |
| 29 | let ReduceArgs { |
| 30 | function, |
| 31 | iterator, |
| 32 | initial, |
| 33 | } = args; |
| 34 | let mut iter = iterator.iter_without_hint(vm)?; |
| 35 | // OptionalOption distinguishes between: |
| 36 | // - Missing: no argument provided → use first element from iterator |
| 37 | // - Present(None): explicitly passed None → use None as initial value |
| 38 | // - Present(Some(v)): passed a value → use that value |
| 39 | let start_value = if let Some(val) = initial.into_option() { |
| 40 | // initial was provided (could be None or Some value) |
| 41 | val.unwrap_or_else(|| vm.ctx.none()) |
| 42 | } else { |
| 43 | // initial was not provided at all |
| 44 | iter.next().transpose()?.ok_or_else(|| { |
| 45 | let exc_type = vm.ctx.exceptions.type_error.to_owned(); |
| 46 | vm.new_exception_msg( |
| 47 | exc_type, |
| 48 | "reduce() of empty sequence with no initial value".into(), |
| 49 | ) |
| 50 | })? |
| 51 | }; |
| 52 | |
| 53 | let mut accumulator = start_value; |
| 54 | for next_obj in iter { |
| 55 | accumulator = function.call((accumulator, next_obj?), vm)? |
| 56 | } |
| 57 | Ok(accumulator) |
| 58 | } |
| 59 | |
| 60 | // Placeholder singleton for partial arguments |
| 61 | // The singleton is stored as _instance on the type class |
nothing calls this directly
no test coverage detected