@@ -281,9 +281,69 @@ fn lang_map(args: Vec<Object>) -> Object {
281281 }
282282}
283283
284- // TODO
285284fn lang_filter ( args : Vec < Object > ) -> Object {
286- Object :: Error ( String :: from ( "TODO: filter is not implemented yet" ) )
285+ if args. len ( ) != 2 {
286+ return Object :: Error ( format ! (
287+ "wrong number of arguments to filter: got={}, want=2" ,
288+ args. len( )
289+ ) ) ;
290+ }
291+
292+ match ( & args[ 0 ] , & args[ 1 ] ) {
293+ ( Object :: Array ( arr) , Object :: Func ( params, body, env) ) => {
294+ let mut new_array: Vec < Object > = Vec :: new ( ) ;
295+
296+ // We need to make sure the function accepts one argument
297+ if params. len ( ) != 1 {
298+ return Object :: Error ( format ! (
299+ "filter function expects a function with exactly one parameter, got {} parameters" ,
300+ params. len( )
301+ ) ) ;
302+ }
303+
304+ for item in arr {
305+ // Create a new environment for each function call, with the closure env as outer
306+ let mut scoped_env = Env :: new_with_outer ( Rc :: clone ( env) ) ;
307+
308+ // Bind the current array item to the function's parameter
309+ let Ident ( param_name) = params[ 0 ] . clone ( ) ;
310+ scoped_env. set ( param_name, item) ;
311+
312+ // Create a new evaluator with this scoped environment
313+ let mut evaluator = Evaluator :: new ( Rc :: new ( RefCell :: new ( scoped_env) ) ) ;
314+
315+ // Evaluate the function body
316+ let result = match evaluator. eval_block_stmt ( body. clone ( ) ) {
317+ Some ( Object :: ReturnValue ( value) ) => * value,
318+ Some ( obj) => {
319+ if let Object :: Error ( _) = obj {
320+ return obj;
321+ }
322+ obj
323+ }
324+ None => Object :: Null ,
325+ } ;
326+
327+ // Only include the item if the function returns a truthy value
328+ if Evaluator :: is_truthy ( result) {
329+ new_array. push ( item. clone ( ) ) ;
330+ }
331+ }
332+
333+ Object :: Array ( new_array)
334+ }
335+ ( Object :: Array ( _) , Object :: Builtin ( _, _) ) => Object :: Error ( format ! (
336+ "cannot use builtin functions with filter yet; use a function literal"
337+ ) ) ,
338+ ( Object :: Array ( _) , not_func) => Object :: Error ( format ! (
339+ "second argument to `filter` must be a function, got {}" ,
340+ not_func
341+ ) ) ,
342+ ( not_array, _) => Object :: Error ( format ! (
343+ "first argument to `filter` must be an array, got {}" ,
344+ not_array
345+ ) ) ,
346+ }
287347}
288348
289349// TODO
0 commit comments