diff --git a/lib/src/base/iterable_extension.dart b/lib/src/base/iterable_extension.dart index 05a7f4d..d79b4f7 100644 --- a/lib/src/base/iterable_extension.dart +++ b/lib/src/base/iterable_extension.dart @@ -136,6 +136,14 @@ extension FicIterableExtension on Iterable { /// expect(['a', 'ab', 'abc', 'abcd', 'abcde'].sumBy((e) => e.length), 15); /// ``` N sumBy(N Function(T element) mapper) { + // If the iterable is empty but N is double + // then result will be an int because 0 is an int + // therefore result as N (which in this case will be: 0 as double) + // will throw an error + if (isEmpty) { + return _zeroOf(); + } + num result = 0; for (final value in this) { result = result + mapper(value); @@ -143,6 +151,17 @@ extension FicIterableExtension on Iterable { return result as N; } + /// Returns a zero of type [N]. + N _zeroOf() { + // num is a sealed class with only two subclasses: int and double + // therefore this function should never throw + return switch (N) { + const (int) => 0 as N, + const (double) => 0.0 as N, + _ => throw UnsupportedError("Unsupported type: $N"), + }; + } + /// The arithmetic mean of the elements of a non-empty iterable. /// The arithmetic mean is the sum of the elements divided by the number of elements. /// If iterable is empty it returns 0. diff --git a/test/base/iterable_extension_test.dart b/test/base/iterable_extension_test.dart index 6e4e390..945dffa 100644 --- a/test/base/iterable_extension_test.dart +++ b/test/base/iterable_extension_test.dart @@ -35,6 +35,8 @@ void main() { expect(['a'].sumBy((e) => e.length), 1); expect(['a', 'ab', 'abc', 'abcd', 'abcde'].sumBy((e) => e.length), 15); expect(['a', 'ab', 'abc', 'abcd', 'abcde'].map((e) => e.length).sum, 15); + expect([].sumBy((e) => e), 0.0); + expect([].sumBy((e) => e), 0); }); test('averageBy', () {