Once in a while we all need to quickly return multiple values from a function, and look for a way to create a new type on the fly.
In Python I can return a tuple
def get_trio1():
return (True, 23, "no")
(_, first1, second1) = get_trio1()
print(first1)
print(second1)
ignore one of the values, and retrieve both of the other two on the fly in one assignment.
I can likewise return an array.
def get_trio2():
return [True, 23, "no"]
[_, first2, second2] = get_trio2()
print(first2)
print(second2)
But both of these are brittle. If I edit the code to add a value, particularly if it's within the three already defined, the revised code could fail silently.
Which is why the nicest solution is to create a dict
on the fly.
def get_trio3():
return {"b": True, "i": 23, "s": "no"}
r = get_trio3()
print(r["i"])
print(r["s"])
The use of named members means that maintaining the code is considerably safer.
What is the closest I can do to get the same safety in Dart? Is defining a class for the return type necessary?
In case it matters, the context is avoiding List<List<dynamic>>
when returning a future.
Future<List<dynamic>> loadAsset() async =>
return await Future.wait([
rootBundle.loadString('assets/file1.txt'),
rootBundle.loadString('assets/file2.txt'),
]);
Update
Using Stephen's answer for a future introduces a problem. Future.wait
is hardwired to use an array Iterable.
Future<Map<String, dynamic>> loadAsset() async =>
return await Future.wait({
"first": rootBundle.loadString('assets/file1.txt'),
"second": rootBundle.loadString('assets/file2.txt'),
});
Your loadAsset
function returns a Future<List<dynamic>>
because that's how you declared it. You could have declared it to return a Future<List<String>>
instead.
Future.wait
is hardwired to use an array.
Especially since Dart is a statically-typed language, you can't really expect it to take both a List
and some Map
with your custom semantics. You could write your own version:
Future<Map<String, T>> myFutureWait<T>(Map<String, Future<T>> futuresMap) async {
var keys = futuresMap.keys.toList();
var values = futuresMap.values.toList();
var results = await Future.wait<T>(values);
return Map.fromIterables(keys, results);
}