diff --git a/vlib/v/gen/c/array.v b/vlib/v/gen/c/array.v index d1f74d639e..b6ea4d721f 100644 --- a/vlib/v/gen/c/array.v +++ b/vlib/v/gen/c/array.v @@ -331,6 +331,19 @@ fn (mut g Gen) array_init_with_fields(node ast.ArrayInit, elem_type Type, is_amp } } +fn (mut g Gen) write_closure_fn(mut expr ast.AnonFn) { + var := g.new_tmp_var() + line := g.go_before_stmt(0).trim_space() + g.empty_line = true + fn_ptr_name := g.fn_var_signature(expr.decl.return_type, expr.decl.params.map(it.typ), + var) + g.write('${fn_ptr_name} = ') + g.gen_anon_fn(mut expr) + g.writeln(';') + g.write(line) + g.write('${var}(it)') +} + // `nums.map(it % 2 == 0)` fn (mut g Gen) gen_array_map(node ast.CallExpr) { g.inside_lambda = true @@ -364,8 +377,12 @@ fn (mut g Gen) gen_array_map(node ast.CallExpr) { match mut expr { ast.AnonFn { g.write('${ret_elem_type} ti = ') - g.gen_anon_fn_decl(mut expr) - g.write('${expr.decl.name}(it)') + if expr.inherited_vars.len > 0 { + g.write_closure_fn(mut expr) + } else { + g.gen_anon_fn_decl(mut expr) + g.write('${expr.decl.name}(it)') + } } ast.Ident { g.write('${ret_elem_type} ti = ') @@ -559,8 +576,12 @@ fn (mut g Gen) gen_array_filter(node ast.CallExpr) { match mut expr { ast.AnonFn { g.write('if (') - g.gen_anon_fn_decl(mut expr) - g.write('${expr.decl.name}(it)') + if expr.inherited_vars.len > 0 { + g.write_closure_fn(mut expr) + } else { + g.gen_anon_fn_decl(mut expr) + g.write('${expr.decl.name}(it)') + } } ast.Ident { g.write('if (') @@ -918,8 +939,12 @@ fn (mut g Gen) gen_array_any(node ast.CallExpr) { match mut expr { ast.AnonFn { g.write('if (') - g.gen_anon_fn_decl(mut expr) - g.write('${expr.decl.name}(it)') + if expr.inherited_vars.len > 0 { + g.write_closure_fn(mut expr) + } else { + g.gen_anon_fn_decl(mut expr) + g.write('${expr.decl.name}(it)') + } } ast.Ident { g.write('if (') @@ -994,8 +1019,12 @@ fn (mut g Gen) gen_array_all(node ast.CallExpr) { match mut expr { ast.AnonFn { g.write('if (!(') - g.gen_anon_fn_decl(mut expr) - g.write('${expr.decl.name}(it)') + if expr.inherited_vars.len > 0 { + g.write_closure_fn(mut expr) + } else { + g.gen_anon_fn_decl(mut expr) + g.write('${expr.decl.name}(it)') + } } ast.Ident { g.write('if (!(') diff --git a/vlib/v/tests/array_filter_using_direct_closure_test.v b/vlib/v/tests/array_filter_using_direct_closure_test.v new file mode 100644 index 0000000000..dd849321b9 --- /dev/null +++ b/vlib/v/tests/array_filter_using_direct_closure_test.v @@ -0,0 +1,42 @@ +struct File { + name string + typ string + is_dir bool +} + +fn filter(all_files []File, interested_file File) []File { + println(interested_file) + return all_files.filter(fn [interested_file] (f File) bool { + println(interested_file) + return true + }) +} + +fn test_array_filter_using_direct_closure() { + filenames := ['one', 'two', 'three'] + files := filenames.map(fn (f string) File { + return File{ + name: f + typ: if f == 'one' { + 'file' + } else { + 'dir' + } + is_dir: if f == 'one' { + false + } else { + true + } + } + }) + + ret := filter(files, files[0]) + println(ret) + assert ret.len == 3 + assert ret[0].name == 'one' + assert ret[0].typ == 'file' + assert ret[1].name == 'two' + assert ret[1].typ == 'dir' + assert ret[2].name == 'three' + assert ret[2].typ == 'dir' +}