1" Test filter() and map()
2
3" list with expression string
4func Test_filter_map_list_expr_string()
5  " filter()
6  call assert_equal([2, 3, 4], filter([1, 2, 3, 4], 'v:val > 1'))
7  call assert_equal([3, 4], filter([1, 2, 3, 4], 'v:key > 1'))
8  call assert_equal([], filter([1, 2, 3, 4], 0))
9
10  " map()
11  call assert_equal([2, 4, 6, 8], map([1, 2, 3, 4], 'v:val * 2'))
12  call assert_equal([0, 2, 4, 6], map([1, 2, 3, 4], 'v:key * 2'))
13  call assert_equal([9, 9, 9, 9], map([1, 2, 3, 4], 9))
14  call assert_equal([7, 7, 7], map([1, 2, 3], ' 7 '))
15endfunc
16
17" dict with expression string
18func Test_filter_map_dict_expr_string()
19  let dict = {"foo": 1, "bar": 2, "baz": 3}
20
21  " filter()
22  call assert_equal({"bar": 2, "baz": 3}, filter(copy(dict), 'v:val > 1'))
23  call assert_equal({"foo": 1, "baz": 3}, filter(copy(dict), 'v:key > "bar"'))
24  call assert_equal({}, filter(copy(dict), 0))
25
26  " map()
27  call assert_equal({"foo": 2, "bar": 4, "baz": 6}, map(copy(dict), 'v:val * 2'))
28  call assert_equal({"foo": "f", "bar": "b", "baz": "b"}, map(copy(dict), 'v:key[0]'))
29  call assert_equal({"foo": 9, "bar": 9, "baz": 9}, map(copy(dict), 9))
30endfunc
31
32" list with funcref
33func Test_filter_map_list_expr_funcref()
34  " filter()
35  func! s:filter1(index, val) abort
36    return a:val > 1
37  endfunc
38  call assert_equal([2, 3, 4], filter([1, 2, 3, 4], function('s:filter1')))
39
40  func! s:filter2(index, val) abort
41    return a:index > 1
42  endfunc
43  call assert_equal([3, 4], filter([1, 2, 3, 4], function('s:filter2')))
44
45  " map()
46  func! s:filter3(index, val) abort
47    return a:val * 2
48  endfunc
49  call assert_equal([2, 4, 6, 8], map([1, 2, 3, 4], function('s:filter3')))
50
51  func! s:filter4(index, val) abort
52    return a:index * 2
53  endfunc
54  call assert_equal([0, 2, 4, 6], map([1, 2, 3, 4], function('s:filter4')))
55endfunc
56
57func Test_filter_map_nested()
58  let x = {"x":10}
59  let r = map(range(2), 'filter(copy(x), "1")')
60  call assert_equal([x, x], r)
61
62  let r = map(copy(x), 'filter(copy(x), "1")')
63  call assert_equal({"x": x}, r)
64endfunc
65
66" dict with funcref
67func Test_filter_map_dict_expr_funcref()
68  let dict = {"foo": 1, "bar": 2, "baz": 3}
69
70  " filter()
71  func! s:filter1(key, val) abort
72    return a:val > 1
73  endfunc
74  call assert_equal({"bar": 2, "baz": 3}, filter(copy(dict), function('s:filter1')))
75
76  func! s:filter2(key, val) abort
77    return a:key > "bar"
78  endfunc
79  call assert_equal({"foo": 1, "baz": 3}, filter(copy(dict), function('s:filter2')))
80
81  " map()
82  func! s:filter3(key, val) abort
83    return a:val * 2
84  endfunc
85  call assert_equal({"foo": 2, "bar": 4, "baz": 6}, map(copy(dict), function('s:filter3')))
86
87  func! s:filter4(key, val) abort
88    return a:key[0]
89  endfunc
90  call assert_equal({"foo": "f", "bar": "b", "baz": "b"}, map(copy(dict), function('s:filter4')))
91endfunc
92
93func Test_map_filter_fails()
94  call assert_fails('call map([1], "42 +")', 'E15:')
95  call assert_fails('call filter([1], "42 +")', 'E15:')
96  call assert_fails("let l = map('abc', '\"> \" . v:val')", 'E896:')
97  call assert_fails("let l = filter('abc', '\"> \" . v:val')", 'E896:')
98  call assert_fails("let l = filter([1, 2, 3], '{}')", 'E728:')
99  call assert_fails("let l = filter({'k' : 10}, '{}')", 'E728:')
100  call assert_fails("let l = filter([1, 2], {})", 'E731:')
101  call assert_equal(test_null_list(), filter(test_null_list(), 0))
102  call assert_equal(test_null_dict(), filter(test_null_dict(), 0))
103  call assert_equal(test_null_list(), map(test_null_list(), '"> " .. v:val'))
104  call assert_equal(test_null_dict(), map(test_null_dict(), '"> " .. v:val'))
105  call assert_equal([1, 2, 3], filter([1, 2, 3], test_null_function()))
106  call assert_fails("let l = filter([1, 2], function('min'))", 'E118:')
107  call assert_equal([1, 2, 3], filter([1, 2, 3], test_null_partial()))
108  call assert_fails("let l = filter([1, 2], {a, b, c -> 1})", 'E119:')
109endfunc
110
111func Test_map_and_modify()
112  let l = ["abc"]
113  " cannot change the list halfway a map()
114  call assert_fails('call map(l, "remove(l, 0)[0]")', 'E741:')
115
116  let d = #{a: 1, b: 2, c: 3}
117  call assert_fails('call map(d, "remove(d, v:key)[0]")', 'E741:')
118  call assert_fails('echo map(d, {k,v -> remove(d, k)})', 'E741:')
119endfunc
120
121func Test_mapnew_dict()
122  let din = #{one: 1, two: 2}
123  let dout = mapnew(din, {k, v -> string(v)})
124  call assert_equal(#{one: 1, two: 2}, din)
125  call assert_equal(#{one: '1', two: '2'}, dout)
126
127  const dconst = #{one: 1, two: 2, three: 3}
128  call assert_equal(#{one: 2, two: 3, three: 4}, mapnew(dconst, {_, v -> v + 1}))
129endfunc
130
131func Test_mapnew_list()
132  let lin = [1, 2, 3]
133  let lout = mapnew(lin, {k, v -> string(v)})
134  call assert_equal([1, 2, 3], lin)
135  call assert_equal(['1', '2', '3'], lout)
136
137  const lconst = [1, 2, 3]
138  call assert_equal([2, 3, 4], mapnew(lconst, {_, v -> v + 1}))
139endfunc
140
141func Test_mapnew_blob()
142  let bin = 0z123456
143  let bout = mapnew(bin, {k, v -> k == 1 ? 0x99 : v})
144  call assert_equal(0z123456, bin)
145  call assert_equal(0z129956, bout)
146endfunc
147
148" vim: shiftwidth=2 sts=2 expandtab
149