forked from aniani/vim
patch 8.2.3848: cannot use reduce() for a string
Problem: Cannot use reduce() for a string. Solution: Make reduce() work with a string. (Naruhiko Nishino, closes #9366)
This commit is contained in:
parent
605ec91e5a
commit
0ccb5842f5
@ -8959,9 +8959,9 @@ readfile({fname} [, {type} [, {max}]])
|
|||||||
|
|
||||||
reduce({object}, {func} [, {initial}]) *reduce()* *E998*
|
reduce({object}, {func} [, {initial}]) *reduce()* *E998*
|
||||||
{func} is called for every item in {object}, which can be a
|
{func} is called for every item in {object}, which can be a
|
||||||
|List| or a |Blob|. {func} is called with two arguments: the
|
|String|, |List| or a |Blob|. {func} is called with two arguments:
|
||||||
result so far and current item. After processing all items
|
the result so far and current item. After processing all
|
||||||
the result is returned.
|
items the result is returned.
|
||||||
|
|
||||||
{initial} is the initial result. When omitted, the first item
|
{initial} is the initial result. When omitted, the first item
|
||||||
in {object} is used and {func} is first called for the second
|
in {object} is used and {func} is first called for the second
|
||||||
@ -8972,6 +8972,7 @@ reduce({object}, {func} [, {initial}]) *reduce()* *E998*
|
|||||||
echo reduce([1, 3, 5], { acc, val -> acc + val })
|
echo reduce([1, 3, 5], { acc, val -> acc + val })
|
||||||
echo reduce(['x', 'y'], { acc, val -> acc .. val }, 'a')
|
echo reduce(['x', 'y'], { acc, val -> acc .. val }, 'a')
|
||||||
echo reduce(0z1122, { acc, val -> 2 * acc + val })
|
echo reduce(0z1122, { acc, val -> 2 * acc + val })
|
||||||
|
echo reduce('xyz', { acc, val -> acc .. ',' .. val })
|
||||||
<
|
<
|
||||||
Can also be used as a |method|: >
|
Can also be used as a |method|: >
|
||||||
echo mylist->reduce({ acc, val -> acc + val }, 0)
|
echo mylist->reduce({ acc, val -> acc + val }, 0)
|
||||||
|
@ -843,4 +843,8 @@ EXTERN char e_highlight_group_name_too_long[]
|
|||||||
EXTERN char e_argument_of_str_must_be_list_string_dictionary_or_blob[]
|
EXTERN char e_argument_of_str_must_be_list_string_dictionary_or_blob[]
|
||||||
INIT(= N_("E1250: Argument of %s must be a List, String, Dictionary or Blob"));
|
INIT(= N_("E1250: Argument of %s must be a List, String, Dictionary or Blob"));
|
||||||
EXTERN char e_list_dict_blob_or_string_required_for_argument_nr[]
|
EXTERN char e_list_dict_blob_or_string_required_for_argument_nr[]
|
||||||
INIT(= N_("E1228: List, Dictionary, Blob or String required for argument %d"));
|
INIT(= N_("E1251: List, Dictionary, Blob or String required for argument %d"));
|
||||||
|
EXTERN char e_string_list_or_blob_required_for_argument_nr[]
|
||||||
|
INIT(= N_("E1252: String, List or Blob required for argument %d"));
|
||||||
|
EXTERN char e_string_expected_for_argument_nr[]
|
||||||
|
INIT(= N_("E1253: String expected for argument %d"));
|
||||||
|
@ -464,6 +464,21 @@ arg_list_or_dict_or_blob_or_string(type_T *type, argcontext_T *context)
|
|||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check "type" is a list of 'any' or a blob or a string.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
arg_string_list_or_blob(type_T *type, argcontext_T *context)
|
||||||
|
{
|
||||||
|
if (type->tt_type == VAR_ANY
|
||||||
|
|| type->tt_type == VAR_LIST
|
||||||
|
|| type->tt_type == VAR_BLOB
|
||||||
|
|| type->tt_type == VAR_STRING)
|
||||||
|
return OK;
|
||||||
|
arg_type_mismatch(&t_list_any, type, context->arg_idx + 1);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check "type" is a job.
|
* Check "type" is a job.
|
||||||
*/
|
*/
|
||||||
@ -817,7 +832,7 @@ static argcheck_T arg2_mapfilter[] = {arg_list_or_dict_or_blob_or_string, NULL};
|
|||||||
static argcheck_T arg25_matchadd[] = {arg_string, arg_string, arg_number, arg_number, arg_dict_any};
|
static argcheck_T arg25_matchadd[] = {arg_string, arg_string, arg_number, arg_number, arg_dict_any};
|
||||||
static argcheck_T arg25_matchaddpos[] = {arg_string, arg_list_any, arg_number, arg_number, arg_dict_any};
|
static argcheck_T arg25_matchaddpos[] = {arg_string, arg_list_any, arg_number, arg_number, arg_dict_any};
|
||||||
static argcheck_T arg119_printf[] = {arg_string_or_nr, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
static argcheck_T arg119_printf[] = {arg_string_or_nr, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||||
static argcheck_T arg23_reduce[] = {arg_list_or_blob, NULL, NULL};
|
static argcheck_T arg23_reduce[] = {arg_string_list_or_blob, NULL, NULL};
|
||||||
static argcheck_T arg24_remote_expr[] = {arg_string, arg_string, arg_string, arg_number};
|
static argcheck_T arg24_remote_expr[] = {arg_string, arg_string, arg_string, arg_number};
|
||||||
static argcheck_T arg23_remove[] = {arg_list_or_dict_or_blob, arg_remove2, arg_number};
|
static argcheck_T arg23_remove[] = {arg_list_or_dict_or_blob, arg_remove2, arg_number};
|
||||||
static argcheck_T arg2_repeat[] = {arg_repeat1, arg_number};
|
static argcheck_T arg2_repeat[] = {arg_repeat1, arg_number};
|
||||||
|
88
src/list.c
88
src/list.c
@ -313,6 +313,28 @@ listitem_alloc(void)
|
|||||||
return ALLOC_ONE(listitem_T);
|
return ALLOC_ONE(listitem_T);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make a typval_T of the first character of "input" and store it in "output".
|
||||||
|
* Return OK or FAIL.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
tv_get_first_char(char_u *input, typval_T *output)
|
||||||
|
{
|
||||||
|
char_u buf[MB_MAXBYTES + 1];
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (input == NULL || output == NULL)
|
||||||
|
return FAIL;
|
||||||
|
|
||||||
|
len = has_mbyte ? mb_ptr2len(input) : 1;
|
||||||
|
STRNCPY(buf, input, len);
|
||||||
|
buf[len] = NUL;
|
||||||
|
output->v_type = VAR_STRING;
|
||||||
|
output->vval.v_string = vim_strsave(buf);
|
||||||
|
|
||||||
|
return output->vval.v_string == NULL ? FAIL : OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Free a list item, unless it was allocated together with the list itself.
|
* Free a list item, unless it was allocated together with the list itself.
|
||||||
* Does not clear the value. Does not notify watchers.
|
* Does not clear the value. Does not notify watchers.
|
||||||
@ -2492,7 +2514,6 @@ filter_map(typval_T *argvars, typval_T *rettv, filtermap_T filtermap)
|
|||||||
char_u *p;
|
char_u *p;
|
||||||
typval_T tv;
|
typval_T tv;
|
||||||
garray_T ga;
|
garray_T ga;
|
||||||
char_u buf[MB_MAXBYTES + 1];
|
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
// set_vim_var_nr() doesn't set the type
|
// set_vim_var_nr() doesn't set the type
|
||||||
@ -2503,16 +2524,9 @@ filter_map(typval_T *argvars, typval_T *rettv, filtermap_T filtermap)
|
|||||||
{
|
{
|
||||||
typval_T newtv;
|
typval_T newtv;
|
||||||
|
|
||||||
if (has_mbyte)
|
if (tv_get_first_char(p, &tv) == FAIL)
|
||||||
len = mb_ptr2len(p);
|
break;
|
||||||
else
|
len = STRLEN(tv.vval.v_string);
|
||||||
len = 1;
|
|
||||||
|
|
||||||
STRNCPY(buf, p, len);
|
|
||||||
buf[len] = NUL;
|
|
||||||
|
|
||||||
tv.v_type = VAR_STRING;
|
|
||||||
tv.vval.v_string = vim_strsave(buf);
|
|
||||||
|
|
||||||
set_vim_var_nr(VV_KEY, idx);
|
set_vim_var_nr(VV_KEY, idx);
|
||||||
if (filter_map_one(&tv, expr, filtermap, &newtv, &rem) == FAIL
|
if (filter_map_one(&tv, expr, filtermap, &newtv, &rem) == FAIL
|
||||||
@ -3248,12 +3262,17 @@ f_reduce(typval_T *argvars, typval_T *rettv)
|
|||||||
partial_T *partial = NULL;
|
partial_T *partial = NULL;
|
||||||
funcexe_T funcexe;
|
funcexe_T funcexe;
|
||||||
typval_T argv[3];
|
typval_T argv[3];
|
||||||
|
int r;
|
||||||
|
int called_emsg_start = called_emsg;
|
||||||
|
|
||||||
if (argvars[0].v_type != VAR_LIST && argvars[0].v_type != VAR_BLOB)
|
if (in_vim9script()
|
||||||
{
|
&& check_for_string_or_list_or_blob_arg(argvars, 0) == FAIL)
|
||||||
emsg(_(e_listblobreq));
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
if (argvars[0].v_type != VAR_STRING
|
||||||
|
&& argvars[0].v_type != VAR_LIST
|
||||||
|
&& argvars[0].v_type != VAR_BLOB)
|
||||||
|
semsg(_(e_string_list_or_blob_required), "reduce()");
|
||||||
|
|
||||||
if (argvars[1].v_type == VAR_FUNC)
|
if (argvars[1].v_type == VAR_FUNC)
|
||||||
func_name = argvars[1].vval.v_string;
|
func_name = argvars[1].vval.v_string;
|
||||||
@ -3278,8 +3297,6 @@ f_reduce(typval_T *argvars, typval_T *rettv)
|
|||||||
{
|
{
|
||||||
list_T *l = argvars[0].vval.v_list;
|
list_T *l = argvars[0].vval.v_list;
|
||||||
listitem_T *li = NULL;
|
listitem_T *li = NULL;
|
||||||
int r;
|
|
||||||
int called_emsg_start = called_emsg;
|
|
||||||
|
|
||||||
if (l != NULL)
|
if (l != NULL)
|
||||||
CHECK_LIST_MATERIALIZE(l);
|
CHECK_LIST_MATERIALIZE(l);
|
||||||
@ -3319,6 +3336,43 @@ f_reduce(typval_T *argvars, typval_T *rettv)
|
|||||||
l->lv_lock = prev_locked;
|
l->lv_lock = prev_locked;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (argvars[0].v_type == VAR_STRING)
|
||||||
|
{
|
||||||
|
char_u *p = tv_get_string(&argvars[0]);
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (argvars[2].v_type == VAR_UNKNOWN)
|
||||||
|
{
|
||||||
|
if (*p == NUL)
|
||||||
|
{
|
||||||
|
semsg(_(e_reduceempty), "String");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (tv_get_first_char(p, rettv) == FAIL)
|
||||||
|
return;
|
||||||
|
p += STRLEN(rettv->vval.v_string);
|
||||||
|
}
|
||||||
|
else if (argvars[2].v_type != VAR_STRING)
|
||||||
|
{
|
||||||
|
semsg(_(e_string_expected_for_argument_nr), 3);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
copy_tv(&argvars[2], rettv);
|
||||||
|
|
||||||
|
for ( ; *p != NUL; p += len)
|
||||||
|
{
|
||||||
|
argv[0] = *rettv;
|
||||||
|
if (tv_get_first_char(p, &argv[1]) == FAIL)
|
||||||
|
break;
|
||||||
|
len = STRLEN(argv[1].vval.v_string);
|
||||||
|
r = call_func(func_name, -1, rettv, 2, argv, &funcexe);
|
||||||
|
clear_tv(&argv[0]);
|
||||||
|
clear_tv(&argv[1]);
|
||||||
|
if (r == FAIL || called_emsg != called_emsg_start)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
blob_T *b = argvars[0].vval.v_blob;
|
blob_T *b = argvars[0].vval.v_blob;
|
||||||
|
@ -34,6 +34,7 @@ int check_for_opt_lnum_arg(typval_T *args, int idx);
|
|||||||
int check_for_opt_string_or_number_arg(typval_T *args, int idx);
|
int check_for_opt_string_or_number_arg(typval_T *args, int idx);
|
||||||
int check_for_string_or_blob_arg(typval_T *args, int idx);
|
int check_for_string_or_blob_arg(typval_T *args, int idx);
|
||||||
int check_for_string_or_list_arg(typval_T *args, int idx);
|
int check_for_string_or_list_arg(typval_T *args, int idx);
|
||||||
|
int check_for_string_or_list_or_blob_arg(typval_T *args, int idx);
|
||||||
int check_for_opt_string_or_list_arg(typval_T *args, int idx);
|
int check_for_opt_string_or_list_arg(typval_T *args, int idx);
|
||||||
int check_for_string_or_dict_arg(typval_T *args, int idx);
|
int check_for_string_or_dict_arg(typval_T *args, int idx);
|
||||||
int check_for_string_or_number_or_list_arg(typval_T *args, int idx);
|
int check_for_string_or_number_or_list_arg(typval_T *args, int idx);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
" Tests for the List and Dict types
|
" Tests for the List and Dict types
|
||||||
|
scriptencoding utf-8
|
||||||
|
|
||||||
source vim9.vim
|
source vim9.vim
|
||||||
|
|
||||||
@ -936,7 +937,7 @@ func Test_reverse_sort_uniq()
|
|||||||
call assert_fails("call sort([1, 2], function('min'))", "E118:")
|
call assert_fails("call sort([1, 2], function('min'))", "E118:")
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
" reduce a list or a blob
|
" reduce a list, blob or string
|
||||||
func Test_reduce()
|
func Test_reduce()
|
||||||
let lines =<< trim END
|
let lines =<< trim END
|
||||||
call assert_equal(1, reduce([], LSTART acc, val LMIDDLE acc + val LEND, 1))
|
call assert_equal(1, reduce([], LSTART acc, val LMIDDLE acc + val LEND, 1))
|
||||||
@ -959,6 +960,16 @@ func Test_reduce()
|
|||||||
|
|
||||||
call assert_equal(0xff, reduce(0zff, LSTART acc, val LMIDDLE acc + val LEND))
|
call assert_equal(0xff, reduce(0zff, LSTART acc, val LMIDDLE acc + val LEND))
|
||||||
call assert_equal(2 * (2 * 0xaf + 0xbf) + 0xcf, reduce(0zAFBFCF, LSTART acc, val LMIDDLE 2 * acc + val LEND))
|
call assert_equal(2 * (2 * 0xaf + 0xbf) + 0xcf, reduce(0zAFBFCF, LSTART acc, val LMIDDLE 2 * acc + val LEND))
|
||||||
|
|
||||||
|
call assert_equal('x,y,z', 'xyz'->reduce(LSTART acc, val LMIDDLE acc .. ',' .. val LEND))
|
||||||
|
call assert_equal('', ''->reduce(LSTART acc, val LMIDDLE acc .. ',' .. val LEND, ''))
|
||||||
|
call assert_equal('あ,い,う,え,お,😊,💕', 'あいうえお😊💕'->reduce(LSTART acc, val LMIDDLE acc .. ',' .. val LEND))
|
||||||
|
call assert_equal('😊,あ,い,う,え,お,💕', 'あいうえお💕'->reduce(LSTART acc, val LMIDDLE acc .. ',' .. val LEND, '😊'))
|
||||||
|
call assert_equal('ऊ,ॠ,ॡ', reduce('ऊॠॡ', LSTART acc, val LMIDDLE acc .. ',' .. val LEND))
|
||||||
|
call assert_equal('c,à,t', reduce('càt', LSTART acc, val LMIDDLE acc .. ',' .. val LEND))
|
||||||
|
call assert_equal('Å,s,t,r,ö,m', reduce('Åström', LSTART acc, val LMIDDLE acc .. ',' .. val LEND))
|
||||||
|
call assert_equal('Å,s,t,r,ö,m', reduce('Åström', LSTART acc, val LMIDDLE acc .. ',' .. val LEND))
|
||||||
|
call assert_equal(',a,b,c', reduce('abc', LSTART acc, val LMIDDLE acc .. ',' .. val LEND, test_null_string()))
|
||||||
END
|
END
|
||||||
call CheckLegacyAndVim9Success(lines)
|
call CheckLegacyAndVim9Success(lines)
|
||||||
|
|
||||||
@ -967,13 +978,23 @@ func Test_reduce()
|
|||||||
|
|
||||||
call assert_fails("call reduce([], { acc, val -> acc + val })", 'E998: Reduce of an empty List with no initial value')
|
call assert_fails("call reduce([], { acc, val -> acc + val })", 'E998: Reduce of an empty List with no initial value')
|
||||||
call assert_fails("call reduce(0z, { acc, val -> acc + val })", 'E998: Reduce of an empty Blob with no initial value')
|
call assert_fails("call reduce(0z, { acc, val -> acc + val })", 'E998: Reduce of an empty Blob with no initial value')
|
||||||
|
call assert_fails("call reduce('', { acc, val -> acc + val })", 'E998: Reduce of an empty String with no initial value')
|
||||||
|
call assert_fails("call reduce(test_null_string(), { acc, val -> acc + val })", 'E998: Reduce of an empty String with no initial value')
|
||||||
|
|
||||||
call assert_fails("call reduce({}, { acc, val -> acc + val }, 1)", 'E897:')
|
call assert_fails("call reduce({}, { acc, val -> acc + val }, 1)", 'E1098:')
|
||||||
call assert_fails("call reduce(0, { acc, val -> acc + val }, 1)", 'E897:')
|
call assert_fails("call reduce(0, { acc, val -> acc + val }, 1)", 'E1098:')
|
||||||
call assert_fails("call reduce('', { acc, val -> acc + val }, 1)", 'E897:')
|
|
||||||
call assert_fails("call reduce([1, 2], 'Xdoes_not_exist')", 'E117:')
|
call assert_fails("call reduce([1, 2], 'Xdoes_not_exist')", 'E117:')
|
||||||
call assert_fails("echo reduce(0z01, { acc, val -> 2 * acc + val }, '')", 'E39:')
|
call assert_fails("echo reduce(0z01, { acc, val -> 2 * acc + val }, '')", 'E39:')
|
||||||
|
|
||||||
|
call assert_fails("vim9 reduce(0, (acc, val) => (acc .. val), '')", 'E1252:')
|
||||||
|
call assert_fails("vim9 reduce({}, (acc, val) => (acc .. val), '')", 'E1252:')
|
||||||
|
call assert_fails("vim9 reduce(0.1, (acc, val) => (acc .. val), '')", 'E1252:')
|
||||||
|
call assert_fails("vim9 reduce(function('tr'), (acc, val) => (acc .. val), '')", 'E1252:')
|
||||||
|
call assert_fails("call reduce('', { acc, val -> acc + val }, 1)", 'E1253:')
|
||||||
|
call assert_fails("call reduce('', { acc, val -> acc + val }, {})", 'E1253:')
|
||||||
|
call assert_fails("call reduce('', { acc, val -> acc + val }, 0.1)", 'E1253:')
|
||||||
|
call assert_fails("call reduce('', { acc, val -> acc + val }, function('tr'))", 'E1253:')
|
||||||
|
|
||||||
let g:lut = [1, 2, 3, 4]
|
let g:lut = [1, 2, 3, 4]
|
||||||
func EvilRemove()
|
func EvilRemove()
|
||||||
call remove(g:lut, 1)
|
call remove(g:lut, 1)
|
||||||
|
@ -1232,7 +1232,7 @@ def Wrong_dict_key_type(items: list<number>): list<number>
|
|||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_filter()
|
def Test_filter()
|
||||||
CheckDefAndScriptFailure2(['filter(1.1, "1")'], 'E1013: Argument 1: type mismatch, expected list<any> but got float', 'E1228: List, Dictionary, Blob or String required for argument 1')
|
CheckDefAndScriptFailure2(['filter(1.1, "1")'], 'E1013: Argument 1: type mismatch, expected list<any> but got float', 'E1251: List, Dictionary, Blob or String required for argument 1')
|
||||||
assert_equal([], filter([1, 2, 3], '0'))
|
assert_equal([], filter([1, 2, 3], '0'))
|
||||||
assert_equal([1, 2, 3], filter([1, 2, 3], '1'))
|
assert_equal([1, 2, 3], filter([1, 2, 3], '1'))
|
||||||
assert_equal({b: 20}, filter({a: 10, b: 20}, 'v:val == 20'))
|
assert_equal({b: 20}, filter({a: 10, b: 20}, 'v:val == 20'))
|
||||||
@ -2028,9 +2028,9 @@ enddef
|
|||||||
|
|
||||||
def Test_map()
|
def Test_map()
|
||||||
if has('channel')
|
if has('channel')
|
||||||
CheckDefAndScriptFailure2(['map(test_null_channel(), "1")'], 'E1013: Argument 1: type mismatch, expected list<any> but got channel', 'E1228: List, Dictionary, Blob or String required for argument 1')
|
CheckDefAndScriptFailure2(['map(test_null_channel(), "1")'], 'E1013: Argument 1: type mismatch, expected list<any> but got channel', 'E1251: List, Dictionary, Blob or String required for argument 1')
|
||||||
endif
|
endif
|
||||||
CheckDefAndScriptFailure2(['map(1, "1")'], 'E1013: Argument 1: type mismatch, expected list<any> but got number', 'E1228: List, Dictionary, Blob or String required for argument 1')
|
CheckDefAndScriptFailure2(['map(1, "1")'], 'E1013: Argument 1: type mismatch, expected list<any> but got number', 'E1251: List, Dictionary, Blob or String required for argument 1')
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_map_failure()
|
def Test_map_failure()
|
||||||
@ -2147,9 +2147,9 @@ enddef
|
|||||||
|
|
||||||
def Test_mapnew()
|
def Test_mapnew()
|
||||||
if has('channel')
|
if has('channel')
|
||||||
CheckDefAndScriptFailure2(['mapnew(test_null_job(), "1")'], 'E1013: Argument 1: type mismatch, expected list<any> but got job', 'E1228: List, Dictionary, Blob or String required for argument 1')
|
CheckDefAndScriptFailure2(['mapnew(test_null_job(), "1")'], 'E1013: Argument 1: type mismatch, expected list<any> but got job', 'E1251: List, Dictionary, Blob or String required for argument 1')
|
||||||
endif
|
endif
|
||||||
CheckDefAndScriptFailure2(['mapnew(1, "1")'], 'E1013: Argument 1: type mismatch, expected list<any> but got number', 'E1228: List, Dictionary, Blob or String required for argument 1')
|
CheckDefAndScriptFailure2(['mapnew(1, "1")'], 'E1013: Argument 1: type mismatch, expected list<any> but got number', 'E1251: List, Dictionary, Blob or String required for argument 1')
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_mapset()
|
def Test_mapset()
|
||||||
@ -2682,7 +2682,7 @@ def Test_readfile()
|
|||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_reduce()
|
def Test_reduce()
|
||||||
CheckDefAndScriptFailure2(['reduce({a: 10}, "1")'], 'E1013: Argument 1: type mismatch, expected list<any> but got dict<number>', 'E897: List or Blob required')
|
CheckDefAndScriptFailure2(['reduce({a: 10}, "1")'], 'E1013: Argument 1: type mismatch, expected list<any> but got dict<number>', 'E1252: String, List or Blob required for argument 1')
|
||||||
assert_equal(6, [1, 2, 3]->reduce((r, c) => r + c, 0))
|
assert_equal(6, [1, 2, 3]->reduce((r, c) => r + c, 0))
|
||||||
assert_equal(11, 0z0506->reduce((r, c) => r + c, 0))
|
assert_equal(11, 0z0506->reduce((r, c) => r + c, 0))
|
||||||
enddef
|
enddef
|
||||||
|
23
src/typval.c
23
src/typval.c
@ -662,6 +662,23 @@ check_for_string_or_list_arg(typval_T *args, int idx)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Give an error and return FAIL unless "args[idx]" is a string, a list or a
|
||||||
|
* blob.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
check_for_string_or_list_or_blob_arg(typval_T *args, int idx)
|
||||||
|
{
|
||||||
|
if (args[idx].v_type != VAR_STRING
|
||||||
|
&& args[idx].v_type != VAR_LIST
|
||||||
|
&& args[idx].v_type != VAR_BLOB)
|
||||||
|
{
|
||||||
|
semsg(_(e_string_list_or_blob_required_for_argument_nr), idx + 1);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check for an optional string or list argument at 'idx'
|
* Check for an optional string or list argument at 'idx'
|
||||||
*/
|
*/
|
||||||
@ -697,10 +714,7 @@ check_for_string_or_number_or_list_arg(typval_T *args, int idx)
|
|||||||
&& args[idx].v_type != VAR_NUMBER
|
&& args[idx].v_type != VAR_NUMBER
|
||||||
&& args[idx].v_type != VAR_LIST)
|
&& args[idx].v_type != VAR_LIST)
|
||||||
{
|
{
|
||||||
if (idx >= 0)
|
|
||||||
semsg(_(e_string_number_or_list_required_for_argument_nr), idx + 1);
|
semsg(_(e_string_number_or_list_required_for_argument_nr), idx + 1);
|
||||||
else
|
|
||||||
emsg(_(e_stringreq));
|
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
return OK;
|
return OK;
|
||||||
@ -742,10 +756,7 @@ check_for_list_or_blob_arg(typval_T *args, int idx)
|
|||||||
{
|
{
|
||||||
if (args[idx].v_type != VAR_LIST && args[idx].v_type != VAR_BLOB)
|
if (args[idx].v_type != VAR_LIST && args[idx].v_type != VAR_BLOB)
|
||||||
{
|
{
|
||||||
if (idx >= 0)
|
|
||||||
semsg(_(e_list_or_blob_required_for_argument_nr), idx + 1);
|
semsg(_(e_list_or_blob_required_for_argument_nr), idx + 1);
|
||||||
else
|
|
||||||
emsg(_(e_listreq));
|
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
return OK;
|
return OK;
|
||||||
|
@ -749,6 +749,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 */
|
||||||
|
/**/
|
||||||
|
3848,
|
||||||
/**/
|
/**/
|
||||||
3847,
|
3847,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user