mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 8.2.2065: using map() and filter() on a range() is inefficient
Problem: Using map() and filter() on a range() is inefficient. Solution: Do not materialize the range. (closes #7388)
This commit is contained in:
parent
ebec3e29b8
commit
f8ca03bf91
58
src/list.c
58
src/list.c
@ -2173,15 +2173,65 @@ filter_map(typval_T *argvars, typval_T *rettv, filtermap_T filtermap)
|
|||||||
// set_vim_var_nr() doesn't set the type
|
// set_vim_var_nr() doesn't set the type
|
||||||
set_vim_var_type(VV_KEY, VAR_NUMBER);
|
set_vim_var_type(VV_KEY, VAR_NUMBER);
|
||||||
|
|
||||||
CHECK_LIST_MATERIALIZE(l);
|
|
||||||
if (filtermap != FILTERMAP_FILTER && l->lv_lock == 0)
|
if (filtermap != FILTERMAP_FILTER && l->lv_lock == 0)
|
||||||
l->lv_lock = VAR_LOCKED;
|
l->lv_lock = VAR_LOCKED;
|
||||||
|
|
||||||
|
if (l->lv_first == &range_list_item)
|
||||||
|
{
|
||||||
|
varnumber_T val = l->lv_u.nonmat.lv_start;
|
||||||
|
int len = l->lv_len;
|
||||||
|
int stride = l->lv_u.nonmat.lv_stride;
|
||||||
|
|
||||||
|
// List from range(): loop over the numbers
|
||||||
|
l->lv_first = NULL;
|
||||||
|
l->lv_u.mat.lv_last = NULL;
|
||||||
|
l->lv_len = 0;
|
||||||
|
l->lv_u.mat.lv_idx_item = NULL;
|
||||||
|
|
||||||
|
for (idx = 0; idx < len; ++idx)
|
||||||
|
{
|
||||||
|
typval_T tv;
|
||||||
|
typval_T newtv;
|
||||||
|
|
||||||
|
tv.v_type = VAR_NUMBER;
|
||||||
|
tv.v_lock = 0;
|
||||||
|
tv.vval.v_number = val;
|
||||||
|
set_vim_var_nr(VV_KEY, idx);
|
||||||
|
if (filter_map_one(&tv, expr, filtermap, &newtv, &rem)
|
||||||
|
== FAIL)
|
||||||
|
break;
|
||||||
|
if (did_emsg)
|
||||||
|
{
|
||||||
|
clear_tv(&newtv);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (filtermap != FILTERMAP_FILTER)
|
||||||
|
{
|
||||||
|
// map(), mapnew(): always append the new value to the
|
||||||
|
// list
|
||||||
|
if (list_append_tv_move(filtermap == FILTERMAP_MAP
|
||||||
|
? l : l_ret, &newtv) == FAIL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (!rem)
|
||||||
|
{
|
||||||
|
// filter(): append the list item value when not rem
|
||||||
|
if (list_append_tv_move(l, &tv) == FAIL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
val += stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Materialized list from range(): loop over the items
|
||||||
for (li = l->lv_first; li != NULL; li = nli)
|
for (li = l->lv_first; li != NULL; li = nli)
|
||||||
{
|
{
|
||||||
typval_T newtv;
|
typval_T newtv;
|
||||||
|
|
||||||
if (filtermap != FILTERMAP_FILTER
|
if (filtermap != FILTERMAP_FILTER && value_check_lock(
|
||||||
&& value_check_lock(li->li_tv.v_lock, arg_errmsg, TRUE))
|
li->li_tv.v_lock, arg_errmsg, TRUE))
|
||||||
break;
|
break;
|
||||||
nli = li->li_next;
|
nli = li->li_next;
|
||||||
set_vim_var_nr(VV_KEY, idx);
|
set_vim_var_nr(VV_KEY, idx);
|
||||||
@ -2210,6 +2260,8 @@ filter_map(typval_T *argvars, typval_T *rettv, filtermap_T filtermap)
|
|||||||
listitem_remove(l, li);
|
listitem_remove(l, li);
|
||||||
++idx;
|
++idx;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
l->lv_lock = prev_lock;
|
l->lv_lock = prev_lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2302,6 +2302,7 @@ func Test_range()
|
|||||||
|
|
||||||
" filter()
|
" filter()
|
||||||
call assert_equal([1, 3], filter(range(5), 'v:val % 2'))
|
call assert_equal([1, 3], filter(range(5), 'v:val % 2'))
|
||||||
|
call assert_equal([1, 5, 7, 11, 13], filter(filter(range(15), 'v:val % 2'), 'v:val % 3'))
|
||||||
|
|
||||||
" funcref()
|
" funcref()
|
||||||
call assert_equal([0, 1], funcref('TwoArgs', range(2))())
|
call assert_equal([0, 1], funcref('TwoArgs', range(2))())
|
||||||
@ -2358,6 +2359,9 @@ func Test_range()
|
|||||||
|
|
||||||
" map()
|
" map()
|
||||||
call assert_equal([0, 2, 4, 6, 8], map(range(5), 'v:val * 2'))
|
call assert_equal([0, 2, 4, 6, 8], map(range(5), 'v:val * 2'))
|
||||||
|
call assert_equal([3, 5, 7, 9, 11], map(map(range(5), 'v:val * 2'), 'v:val + 3'))
|
||||||
|
call assert_equal([2, 6], map(filter(range(5), 'v:val % 2'), 'v:val * 2'))
|
||||||
|
call assert_equal([2, 4, 8], filter(map(range(5), 'v:val * 2'), 'v:val % 3'))
|
||||||
|
|
||||||
" match()
|
" match()
|
||||||
call assert_equal(3, match(range(5), 3))
|
call assert_equal(3, match(range(5), 3))
|
||||||
|
@ -750,6 +750,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
2065,
|
||||||
/**/
|
/**/
|
||||||
2064,
|
2064,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user