From efad1e71fa699e0d2413d3a6a3ce5a4163e38112 Mon Sep 17 00:00:00 2001 From: SekoiaTree <51149447+SekoiaTree@users.noreply.github.com> Date: Tue, 25 Apr 2023 11:18:27 +0200 Subject: Add sum and product to arrays (#966) --- src/eval/array.rs | 35 +++++++++++++++++++++++++++++++++++ src/eval/methods.rs | 2 ++ 2 files changed, 37 insertions(+) (limited to 'src/eval') diff --git a/src/eval/array.rs b/src/eval/array.rs index b04fdab8..1166ce94 100644 --- a/src/eval/array.rs +++ b/src/eval/array.rs @@ -24,6 +24,7 @@ macro_rules! __array { #[doc(inline)] pub use crate::__array as array; +use crate::eval::ops::{add, mul}; #[doc(hidden)] pub use ecow::eco_vec; @@ -199,6 +200,40 @@ impl Array { Ok(acc) } + /// Calculates the sum of the array's items + pub fn sum(&self, default: Option, span: Span) -> SourceResult { + let mut acc = self + .first() + .map(|x| x.clone()) + .or_else(|_| { + default.ok_or_else(|| { + eco_format!("cannot calculate sum of empty array with no default") + }) + }) + .at(span)?; + for i in self.iter().skip(1) { + acc = add(acc, i.clone()).at(span)?; + } + Ok(acc) + } + + /// Calculates the product of the array's items + pub fn product(&self, default: Option, span: Span) -> SourceResult { + let mut acc = self + .first() + .map(|x| x.clone()) + .or_else(|_| { + default.ok_or_else(|| { + eco_format!("cannot calculate product of empty array with no default") + }) + }) + .at(span)?; + for i in self.iter().skip(1) { + acc = mul(acc, i.clone()).at(span)?; + } + Ok(acc) + } + /// Whether any item matches. pub fn any(&self, vm: &mut Vm, func: Func) -> SourceResult { for item in self.iter() { diff --git a/src/eval/methods.rs b/src/eval/methods.rs index 56d1c7b7..29b729cb 100644 --- a/src/eval/methods.rs +++ b/src/eval/methods.rs @@ -105,6 +105,8 @@ pub fn call( "fold" => { array.fold(vm, args.expect("initial value")?, args.expect("function")?)? } + "sum" => array.sum(args.named("default")?, span)?, + "product" => array.product(args.named("default")?, span)?, "any" => Value::Bool(array.any(vm, args.expect("function")?)?), "all" => Value::Bool(array.all(vm, args.expect("function")?)?), "flatten" => Value::Array(array.flatten()), -- cgit v1.2.3