Using Dart 2.14.2 I ran the following code
void main(List<String> args) {
var a = <int>[1, 2, 3];
final foldValue = a.fold(0, (previousValue, element) => previousValue element);
final reduceValue = a.reduce((previousValue, element) => previousValue element);
}
for the line containing foldValue
the analyzer give me the following error :
Error: The operator ' ' isn't defined for the class 'Object?'.
without giving any error for the line containing reduceValue
.
My question is: what makes List.fold raises such error while List.reduce doesn't?
CodePudding user response:
The List.fold
problem is a well-known limit of the Dart type inference algorithm.
Since you haven't provided a type argument to fold
, the type inference infers static type for each argument independently, then try to combine them to find a valid type argument to fold
itself.
The two arguments are inferred independently and with not type hint.
The 0
argument is easy, it has type int
.
The (previousValue, element) => previousValue element
function is harder.
The algorithm has no clue to what type the first parameter should be. It should be T
, the type parameter of fold
, but we don't know T
yet. It can't use the body, because it can't type analyze the body before it has a type for the parameters (and even if it could, there are many parameter types which would make the body valid; dynamic
, int
, num
, and double
are potential candidates, and there can be more user types which allow you to add int
to them.)
With no hint from the outside, the type inference uses the top-type and gets (Object? previousValue, int element) => ...
. Then it fails to accept previousValue element
.
The reason reduce
doesn't fail is that it has all the necessary information. Both parameters must have type int
, the element type of the list.