--- a/crates/jrsonnet-evaluator/src/arr/mod.rs +++ b/crates/jrsonnet-evaluator/src/arr/mod.rs @@ -9,7 +9,7 @@ use jrsonnet_interner::IBytes; use jrsonnet_ir::Expr; -use crate::{function::NativeFn, Context, Result, Thunk, Val}; +use crate::{function::NativeFn, typed::IntoUntyped, Context, Result, Thunk, Val}; mod spec; pub use spec::{ArrayLike, *}; @@ -71,16 +71,28 @@ Self::new(::new(self, ArrayMapper::WithIndex(mapper))) } - pub fn filter(self, filter: impl Fn(&Val) -> Result) -> Result { + pub fn filter(self, filter: NativeFn!((Thunk) -> bool)) -> Result { // TODO: ArrValue::Picked(inner, indexes) for large arrays + 'eager: { + let mut out = Vec::new(); + for i in self.iter() { + let Ok(i) = i else { + break 'eager; + }; + if filter.call(IntoUntyped::into_lazy_untyped(i.clone()))? { + out.push(i); + } + } + return Ok(Self::eager(out)); + }; + let mut out = Vec::new(); - for i in self.iter() { - let i = i?; - if filter(&i)? { + for i in self.iter_lazy() { + if filter.call(i.clone())? { out.push(i); } } - Ok(Self::eager(out)) + Ok(Self::lazy(out)) } pub fn extended(a: Self, b: Self) -> Self { --- a/crates/jrsonnet-stdlib/src/arrays.rs +++ b/crates/jrsonnet-stdlib/src/arrays.rs @@ -126,11 +126,11 @@ } } -type FilterFunc = NativeFn!((Val) -> bool); +type FilterFunc = NativeFn!((Thunk) -> bool); #[builtin] pub fn builtin_filter(func: FilterFunc, arr: ArrValue) -> Result { - arr.filter(|val| func.call(val.clone())) + arr.filter(func) } #[builtin] @@ -139,7 +139,7 @@ map_func: NativeFn!((Val) -> Val), arr: ArrValue, ) -> Result { - Ok(builtin_filter(filter_func, arr)?.map(map_func)) + Ok(arr.filter(filter_func)?.map(map_func)) } #[builtin]