列表函数中的通用类型推断
Generic type inference in function from lists
我正在处理一些通用列表实用函数,当主变量是列表时,通用函数的类型推断似乎存在问题。这是用以下代码演示的:
List<T> combine<T>(List<T> a, List<T> b, T Function(T a, T b) combiner) {
final list = <T>[];
for (int i = 0; i < a.length && i < b.length; i++) {
list.add(combiner(a[i], b[i]));
}
return list;
}
void main() {
final a = [5, 8];
final b = [7, -3];
final c = combine(a, b, (a, b) => a + b); // Error
print(c);
// Expected: [12, 5]
}
当我按原样使用此代码时,lambda 中的类型推断将 a
和 b
设置为 Object?
,这导致以下错误消息:
The operator '+' can't be unconditionally invoked because the receiver can be 'null'.
Try adding a null check to the target ('!').
按照错误消息所说的操作将消息更改为以下内容:
The operator '+' isn't defined for the type 'Object'.
Try defining the operator '+'.
问题显然是类型推断将参数分配给 Object?
而不是预期的 int
。这可以通过键入参数或显式将泛型类型传递给函数来解决:
final c = combine(a, b, (int a, int b) => a + b);
// OR
final c = combine<int>(a, b, (a, b) => a + b);
但是,这是一个额外的冗长级别,我不想强迫这些实用功能的用户必须这样做(更不用说当我必须向他们解释时这将是一个支持问题去做这个)。有没有办法更改函数签名以使其类型推断按预期工作?
这基本上是 ,但在您的情况下,您可以通过使函数成为扩展方法来回避问题,这样 T
是从接收者而不是参数推导出来的:
extension<T> on List<T> {
List<T> combineWith(List<T> b, T Function(T a, T b) combiner) {
final list = <T>[];
for (int i = 0; i < length && i < b.length; i++) {
list.add(combiner(this[i], b[i]));
}
return list;
}
}
void main() {
final a = [5, 8];
final b = [7, -3];
final c = a.combineWith(b, (a, b) => a + b); // Error
print(c);
// Expected: [12, 5]
}
我正在处理一些通用列表实用函数,当主变量是列表时,通用函数的类型推断似乎存在问题。这是用以下代码演示的:
List<T> combine<T>(List<T> a, List<T> b, T Function(T a, T b) combiner) {
final list = <T>[];
for (int i = 0; i < a.length && i < b.length; i++) {
list.add(combiner(a[i], b[i]));
}
return list;
}
void main() {
final a = [5, 8];
final b = [7, -3];
final c = combine(a, b, (a, b) => a + b); // Error
print(c);
// Expected: [12, 5]
}
当我按原样使用此代码时,lambda 中的类型推断将 a
和 b
设置为 Object?
,这导致以下错误消息:
The operator '+' can't be unconditionally invoked because the receiver can be 'null'. Try adding a null check to the target ('!').
按照错误消息所说的操作将消息更改为以下内容:
The operator '+' isn't defined for the type 'Object'. Try defining the operator '+'.
问题显然是类型推断将参数分配给 Object?
而不是预期的 int
。这可以通过键入参数或显式将泛型类型传递给函数来解决:
final c = combine(a, b, (int a, int b) => a + b);
// OR
final c = combine<int>(a, b, (a, b) => a + b);
但是,这是一个额外的冗长级别,我不想强迫这些实用功能的用户必须这样做(更不用说当我必须向他们解释时这将是一个支持问题去做这个)。有没有办法更改函数签名以使其类型推断按预期工作?
这基本上是 T
是从接收者而不是参数推导出来的:
extension<T> on List<T> {
List<T> combineWith(List<T> b, T Function(T a, T b) combiner) {
final list = <T>[];
for (int i = 0; i < length && i < b.length; i++) {
list.add(combiner(this[i], b[i]));
}
return list;
}
}
void main() {
final a = [5, 8];
final b = [7, -3];
final c = a.combineWith(b, (a, b) => a + b); // Error
print(c);
// Expected: [12, 5]
}