--- a/crates/jrsonnet-evaluator/src/arr/mod.rs +++ b/crates/jrsonnet-evaluator/src/arr/mod.rs @@ -54,7 +54,12 @@ #[must_use] pub fn map(self, mapper: FuncVal) -> Self { - Self::new(MappedArray::new(self, mapper)) + Self::new(>::new(self, mapper)) + } + + #[must_use] + pub fn map_with_index(self, mapper: FuncVal) -> Self { + Self::new(>::new(self, mapper)) } pub fn filter(self, filter: impl Fn(&Val) -> Result) -> Result { --- a/crates/jrsonnet-evaluator/src/arr/spec.rs +++ b/crates/jrsonnet-evaluator/src/arr/spec.rs @@ -430,12 +430,12 @@ } #[derive(Trace, Debug, Clone)] -pub struct MappedArray { +pub struct MappedArray { inner: ArrValue, cached: Cc>>>, mapper: FuncVal, } -impl MappedArray { +impl MappedArray { pub fn new(inner: ArrValue, mapper: FuncVal) -> Self { let len = inner.len(); Self { @@ -444,8 +444,15 @@ mapper, } } + fn evaluate(&self, index: usize, value: Val) -> Result { + if WithIndex { + self.mapper.evaluate_simple(&(index, value), false) + } else { + self.mapper.evaluate_simple(&(value,), false) + } + } } -impl ArrayLike for MappedArray { +impl ArrayLike for MappedArray { fn len(&self) -> usize { self.cached.borrow().len() } @@ -472,7 +479,7 @@ .get(index) .transpose() .expect("index checked") - .and_then(|r| self.mapper.evaluate_simple(&(r,), false)); + .and_then(|r| self.evaluate(index, r)); let new_value = match val { Ok(v) => v, @@ -486,12 +493,12 @@ } fn get_lazy(&self, index: usize) -> Option> { #[derive(Trace)] - struct ArrayElement { - arr_thunk: MappedArray, + struct ArrayElement { + arr_thunk: MappedArray, index: usize, } - impl ThunkValue for ArrayElement { + impl ThunkValue for ArrayElement { type Output = Val; fn get(self: Box) -> Result { --- a/crates/jrsonnet-stdlib/src/arrays.rs +++ b/crates/jrsonnet-stdlib/src/arrays.rs @@ -62,6 +62,12 @@ } #[builtin] +pub fn builtin_map_with_index(func: FuncVal, arr: IndexableVal) -> ArrValue { + let arr = arr.to_array(); + arr.map_with_index(func) +} + +#[builtin] pub fn builtin_flatmap( func: NativeFn<((Either![String, Val],), Val)>, arr: IndexableVal, --- a/crates/jrsonnet-stdlib/src/lib.rs +++ b/crates/jrsonnet-stdlib/src/lib.rs @@ -78,6 +78,7 @@ ("repeat", builtin_repeat::INST), ("slice", builtin_slice::INST), ("map", builtin_map::INST), + ("mapWithIndex", builtin_map_with_index::INST), ("flatMap", builtin_flatmap::INST), ("filter", builtin_filter::INST), ("foldl", builtin_foldl::INST), --- a/crates/jrsonnet-stdlib/src/std.jsonnet +++ b/crates/jrsonnet-stdlib/src/std.jsonnet @@ -3,14 +3,6 @@ thisFile:: error 'std.thisFile is deprecated, to enable its support in jrsonnet - recompile it with "legacy-this-file" support.\nThis will slow down stdlib caching a bit, though', - mapWithIndex(func, arr):: - if !std.isFunction(func) then - error ('std.mapWithIndex first param must be function, got ' + std.type(func)) - else if !std.isArray(arr) && !std.isString(arr) then - error ('std.mapWithIndex second param must be array, got ' + std.type(arr)) - else - std.makeArray(std.length(arr), function(i) func(i, arr[i])), - mapWithKey(func, obj):: if !std.isFunction(func) then error ('std.mapWithKey first param must be function, got ' + std.type(func))