Skip to content

Commit ea69685

Browse files
committed
patch 8.2.1969: Vim9: map() may change the list or dict item type
Problem: Vim9: map() may change the list or dict item type. Solution: Add mapnew().
1 parent 8cebd43 commit ea69685

7 files changed

Lines changed: 204 additions & 52 deletions

File tree

runtime/doc/eval.txt

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2669,8 +2669,9 @@ maparg({name} [, {mode} [, {abbr} [, {dict}]]])
26692669
rhs of mapping {name} in mode {mode}
26702670
mapcheck({name} [, {mode} [, {abbr}]])
26712671
String check for mappings matching {name}
2672-
mapset({mode}, {abbr}, {dict})
2673-
none restore mapping from |maparg()| result
2672+
mapnew({expr1}, {expr2}) List/Dict like |map()| but creates a new List
2673+
or Dictionary
2674+
mapset({mode}, {abbr}, {dict}) none restore mapping from |maparg()| result
26742675
match({expr}, {pat} [, {start} [, {count}]])
26752676
Number position where {pat} matches in {expr}
26762677
matchadd({group}, {pattern} [, {priority} [, {id} [, {dict}]]])
@@ -6987,9 +6988,14 @@ luaeval({expr} [, {expr}]) *luaeval()*
69876988
< {only available when compiled with the |+lua| feature}
69886989

69896990
map({expr1}, {expr2}) *map()*
6990-
{expr1} must be a |List| or a |Dictionary|.
6991+
{expr1} must be a |List|, |Blob| or |Dictionary|.
69916992
Replace each item in {expr1} with the result of evaluating
6992-
{expr2}. {expr2} must be a |string| or |Funcref|.
6993+
{expr2}. For a |Blob| each byte is replaced.
6994+
If the item type changes you may want to use |mapnew()| to
6995+
create a new List or Dictionary. This is required when using
6996+
Vim9 script.
6997+
6998+
{expr2} must be a |string| or |Funcref|.
69936999

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

7027-
< Returns {expr1}, the |List| or |Dictionary| that was filtered.
7028-
When an error is encountered while evaluating {expr2} no
7029-
further items in {expr1} are processed. When {expr2} is a
7030-
Funcref errors inside a function are ignored, unless it was
7031-
defined with the "abort" flag.
7033+
< Returns {expr1}, the |List|, |Blob| or |Dictionary| that was
7034+
filtered. When an error is encountered while evaluating
7035+
{expr2} no further items in {expr1} are processed. When
7036+
{expr2} is a Funcref errors inside a function are ignored,
7037+
unless it was defined with the "abort" flag.
70327038

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

71397145

7140-
mapset({mode}, {abbr}, {dict}) *mapset()*
7146+
mapnew({expr1}, {expr2}) *mapnew()*
7147+
Like |map()| but instead of replacing items in {expr1} a new
7148+
List or Dictionary is created and returned. {expr1} remains
7149+
unchanged.
7150+
7151+
7152+
mapset({mode}, {abbr}, {dict}) *mapset()*
71417153
Restore a mapping from a dictionary returned by |maparg()|.
71427154
{mode} and {abbr} should be the same as for the call to
71437155
|maparg()|. *E460*

runtime/doc/usr_41.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,7 @@ List manipulation: *list-functions*
644644
deepcopy() make a full copy of a List
645645
filter() remove selected items from a List
646646
map() change each List item
647+
mapnew() make a new List with changed items
647648
reduce() reduce a List to a value
648649
sort() sort a List
649650
reverse() reverse the order of a List
@@ -669,6 +670,7 @@ Dictionary manipulation: *dict-functions*
669670
extend() add entries from one Dictionary to another
670671
filter() remove selected entries from a Dictionary
671672
map() change each Dictionary entry
673+
mapnew() make a new Dictionary with changed items
672674
keys() get List of Dictionary keys
673675
values() get List of Dictionary values
674676
items() get List of Dictionary key-value pairs

src/evalfunc.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -479,14 +479,25 @@ ret_job(int argcount UNUSED, type_T **argtypes UNUSED)
479479
{
480480
return &t_job;
481481
}
482-
483482
static type_T *
484483
ret_first_arg(int argcount, type_T **argtypes)
485484
{
486485
if (argcount > 0)
487486
return argtypes[0];
488487
return &t_void;
489488
}
489+
// for map(): returns first argument but item type may differ
490+
static type_T *
491+
ret_first_cont(int argcount UNUSED, type_T **argtypes)
492+
{
493+
if (argtypes[0]->tt_type == VAR_LIST)
494+
return &t_list_any;
495+
if (argtypes[0]->tt_type == VAR_DICT)
496+
return &t_dict_any;
497+
if (argtypes[0]->tt_type == VAR_BLOB)
498+
return argtypes[0];
499+
return &t_any;
500+
}
490501

491502
/*
492503
* Used for getqflist(): returns list if there is no argument, dict if there is
@@ -1115,11 +1126,13 @@ static funcentry_T global_functions[] =
11151126
#endif
11161127
},
11171128
{"map", 2, 2, FEARG_1, NULL,
1118-
ret_any, f_map},
1129+
ret_first_cont, f_map},
11191130
{"maparg", 1, 4, FEARG_1, NULL,
11201131
ret_maparg, f_maparg},
11211132
{"mapcheck", 1, 3, FEARG_1, NULL,
11221133
ret_string, f_mapcheck},
1134+
{"mapnew", 2, 2, FEARG_1, NULL,
1135+
ret_first_cont, f_mapnew},
11231136
{"mapset", 3, 3, FEARG_1, NULL,
11241137
ret_void, f_mapset},
11251138
{"match", 2, 4, FEARG_1, NULL,

0 commit comments

Comments
 (0)