--- a/crates/jrsonnet-stdlib/src/arrays.rs +++ b/crates/jrsonnet-stdlib/src/arrays.rs @@ -1,12 +1,22 @@ +#![allow(non_snake_case)] + use jrsonnet_evaluator::{ error::{ErrorKind::RuntimeError, Result}, function::{builtin, FuncVal}, throw, typed::{BoundedI32, BoundedUsize, Either2, NativeFn, Typed}, val::{equals, ArrValue, IndexableVal, StrValue}, - Either, IStr, Val, + Either, IStr, Thunk, Val, }; +pub(crate) fn eval_on_empty(on_empty: Option>) -> Result { + if let Some(on_empty) = on_empty { + on_empty.evaluate() + } else { + throw!("expected non-empty array") + } +} + #[builtin] pub fn builtin_make_array(sz: BoundedI32<0, { i32::MAX }>, func: FuncVal) -> Result { if *sz == 0 { @@ -230,3 +240,11 @@ } Ok(count) } + +#[builtin] +pub fn builtin_avg(arr: Vec, onEmpty: Option>) -> Result { + if arr.is_empty() { + return eval_on_empty(onEmpty); + } + Ok(Val::Num(arr.iter().sum::() / (arr.len() as f64))) +} --- a/crates/jrsonnet-stdlib/src/lib.rs +++ b/crates/jrsonnet-stdlib/src/lib.rs @@ -81,6 +81,7 @@ ("all", builtin_all::INST), ("member", builtin_member::INST), ("count", builtin_count::INST), + ("avg", builtin_avg::INST), // Math ("abs", builtin_abs::INST), ("sign", builtin_sign::INST), --- a/crates/jrsonnet-stdlib/src/sort.rs +++ b/crates/jrsonnet-stdlib/src/sort.rs @@ -13,6 +13,8 @@ use jrsonnet_gcmodule::Cc; use jrsonnet_parser::BinaryOpType; +use crate::eval_on_empty; + #[derive(Copy, Clone)] enum SortKeyType { Number, @@ -207,13 +209,6 @@ } } -fn eval_on_empty(on_empty: Option>) -> Result { - if let Some(on_empty) = on_empty { - on_empty.evaluate() - } else { - throw!("expected non-empty array") - } -} fn eval_keyf(val: Val, key_f: &Option) -> Result { if let Some(key_f) = key_f {