Skip to content

Commit

Permalink
patch 8.2.1969: Vim9: map() may change the list or dict item type
Browse files Browse the repository at this point in the history
Problem:    Vim9: map() may change the list or dict item type.
Solution:   Add mapnew().
  • Loading branch information
brammool committed Nov 9, 2020
1 parent 8cebd43 commit ea69685
Show file tree
Hide file tree
Showing 7 changed files with 204 additions and 52 deletions.
32 changes: 22 additions & 10 deletions runtime/doc/eval.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2669,8 +2669,9 @@ maparg({name} [, {mode} [, {abbr} [, {dict}]]])
rhs of mapping {name} in mode {mode}
mapcheck({name} [, {mode} [, {abbr}]])
String check for mappings matching {name}
mapset({mode}, {abbr}, {dict})
none restore mapping from |maparg()| result
mapnew({expr1}, {expr2}) List/Dict like |map()| but creates a new List
or Dictionary
mapset({mode}, {abbr}, {dict}) none restore mapping from |maparg()| result
match({expr}, {pat} [, {start} [, {count}]])
Number position where {pat} matches in {expr}
matchadd({group}, {pattern} [, {priority} [, {id} [, {dict}]]])
Expand Down Expand Up @@ -6987,9 +6988,14 @@ luaeval({expr} [, {expr}]) *luaeval()*
< {only available when compiled with the |+lua| feature}

map({expr1}, {expr2}) *map()*
{expr1} must be a |List| or a |Dictionary|.
{expr1} must be a |List|, |Blob| or |Dictionary|.
Replace each item in {expr1} with the result of evaluating
{expr2}. {expr2} must be a |string| or |Funcref|.
{expr2}. For a |Blob| each byte is replaced.
If the item type changes you may want to use |mapnew()| to
create a new List or Dictionary. This is required when using
Vim9 script.

{expr2} must be a |string| or |Funcref|.

If {expr2} is a |string|, inside {expr2} |v:val| has the value
of the current item. For a |Dictionary| |v:key| has the key
Expand Down Expand Up @@ -7024,11 +7030,11 @@ map({expr1}, {expr2}) *map()*
|Dictionary| to remain unmodified make a copy first: >
:let tlist = map(copy(mylist), ' v:val . "\t"')

< Returns {expr1}, the |List| or |Dictionary| that was filtered.
When an error is encountered while evaluating {expr2} no
further items in {expr1} are processed. When {expr2} is a
Funcref errors inside a function are ignored, unless it was
defined with the "abort" flag.
< Returns {expr1}, the |List|, |Blob| or |Dictionary| that was
filtered. When an error is encountered while evaluating
{expr2} no further items in {expr1} are processed. When
{expr2} is a Funcref errors inside a function are ignored,
unless it was defined with the "abort" flag.

Can also be used as a |method|: >
mylist->map(expr2)
Expand Down Expand Up @@ -7137,7 +7143,13 @@ mapcheck({name} [, {mode} [, {abbr}]]) *mapcheck()*
GetKey()->mapcheck('n')


mapset({mode}, {abbr}, {dict}) *mapset()*
mapnew({expr1}, {expr2}) *mapnew()*
Like |map()| but instead of replacing items in {expr1} a new
List or Dictionary is created and returned. {expr1} remains
unchanged.


mapset({mode}, {abbr}, {dict}) *mapset()*
Restore a mapping from a dictionary returned by |maparg()|.
{mode} and {abbr} should be the same as for the call to
|maparg()|. *E460*
Expand Down
2 changes: 2 additions & 0 deletions runtime/doc/usr_41.txt
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,7 @@ List manipulation: *list-functions*
deepcopy() make a full copy of a List
filter() remove selected items from a List
map() change each List item
mapnew() make a new List with changed items
reduce() reduce a List to a value
sort() sort a List
reverse() reverse the order of a List
Expand All @@ -669,6 +670,7 @@ Dictionary manipulation: *dict-functions*
extend() add entries from one Dictionary to another
filter() remove selected entries from a Dictionary
map() change each Dictionary entry
mapnew() make a new Dictionary with changed items
keys() get List of Dictionary keys
values() get List of Dictionary values
items() get List of Dictionary key-value pairs
Expand Down
17 changes: 15 additions & 2 deletions src/evalfunc.c
Original file line number Diff line number Diff line change
Expand Up @@ -479,14 +479,25 @@ ret_job(int argcount UNUSED, type_T **argtypes UNUSED)
{
return &t_job;
}

static type_T *
ret_first_arg(int argcount, type_T **argtypes)
{
if (argcount > 0)
return argtypes[0];
return &t_void;
}
// for map(): returns first argument but item type may differ
static type_T *
ret_first_cont(int argcount UNUSED, type_T **argtypes)
{
if (argtypes[0]->tt_type == VAR_LIST)
return &t_list_any;
if (argtypes[0]->tt_type == VAR_DICT)
return &t_dict_any;
if (argtypes[0]->tt_type == VAR_BLOB)
return argtypes[0];
return &t_any;
}

/*
* Used for getqflist(): returns list if there is no argument, dict if there is
Expand Down Expand Up @@ -1115,11 +1126,13 @@ static funcentry_T global_functions[] =
#endif
},
{"map", 2, 2, FEARG_1, NULL,
ret_any, f_map},
ret_first_cont, f_map},
{"maparg", 1, 4, FEARG_1, NULL,
ret_maparg, f_maparg},
{"mapcheck", 1, 3, FEARG_1, NULL,
ret_string, f_mapcheck},
{"mapnew", 2, 2, FEARG_1, NULL,
ret_first_cont, f_mapnew},
{"mapset", 3, 3, FEARG_1, NULL,
ret_void, f_mapset},
{"match", 2, 4, FEARG_1, NULL,
Expand Down

0 comments on commit ea69685

Please sign in to comment.