Reputation: 103
While trying to update a List of List of Strings in a map using the short notation with the fat arrow I get "This expression has type 'void' and can't be used." error. If I don't use the short notation and instead use an intermediate variable and return it it works fine.
I'm trying to update a map of the following type:
Map<String, List<List<String>>> mapWithAListOfListsOfStrings = {};
This is the code using the fat arrow notation.
void main() {
Map<String, List<List<String>>> mapWithAListOfListsOfStrings = {};
String string1 = 'Lorem ipsum dolor sit amet';
String string2 = 'consectetur adipiscing elit';
for (String string in [string1, string2]) {
List<String> splitString = string.split(' ');
mapWithAListOfListsOfStrings.update('1', (list) => list.add(splitString), ifAbsent: () => [splitString]);
}
print("Map contains: ${mapWithAListOfListsOfStrings.toString()}");
}
This is the error I get:
sample.dart:8:56: Error: This expression has type 'void' and can't be used.
mapWithAListOfListsOfStrings.update('1', (list) => list.add(splitString), ifAbsent: () => [splitString]);
This is my workaround that works:
void main() {
Map<String, List<List<String>>> mapWithAListOfListsOfStrings = {};
String string1 = 'Lorem ipsum dolor sit amet';
String string2 = 'consectetur adipiscing elit';
for (String string in [string1, string2]) {
List<String> splitString = string.split(' ');
mapWithAListOfListsOfStrings.update('1', (list) {
List<List<String>> returnList = list;
returnList.add(splitString);
return returnList;
}, ifAbsent: () => [splitString]);
}
print("Map contains: ${mapWithAListOfListsOfStrings.toString()}");
}
And this is the desired result:
Map contains: {1: [[Lorem, ipsum, dolor, sit, amet], [consectetur, adipiscing, elit]]}
I'm happy to leave it like that. I just wonder why the first approach throws an error.
Thanks in advance.
Upvotes: 0
Views: 96
Reputation: 71653
The problem is indeed that the return type of list.add
is void, and not the list itself. The update
method requires its argument function to return the new value for the provided key, and => list.add(...)
doesn't do that, it just returns void.
Your workaround could be reduced to:
(list) {
list.add(splitString);
return list;
}
or to:
(list) => list..add(splitString)
but the real problem is that you shouldn't be using map.update
at all. That function is intended to replace the existing value for a key, not to keep the list value after adding something to it. You have to go out of your way to return the value again, instead of just using a function which doesn't change the value of the key (except if it isn't here).
I'd write it as:
mapWithAListOfListOfStrings.putIfAbsent('1', () =>[]).add(splitString);
The putIfAbsent
returns the existing value, or inserts a value if there isn't one yet and then returns that value, so this really does:
map['1'] exists
and is a listmap['1'].add(splitString)
It just does so without needing to look up '1'
twice.
Upvotes: 1