Вывод универсального типа в функции из списков

Я работаю над некоторыми универсальными служебными функциями списка, и, похоже, возникает проблема с выводом типа для универсальной функции, когда первичными переменными являются списки. Это демонстрируется с помощью следующего кода:

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]
}

Когда я использую этот код как есть, вывод типа в лямбда-выражении устанавливает 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);

Тем не менее, это дополнительный уровень детализации, который я не хочу заставлять пользователей этих служебных функций делать (не говоря уже о том, что это будет проблемой поддержки, когда мне придется объяснять им, как это сделать). Есть ли способ изменить сигнатуру функции, чтобы вывод типа работал должным образом?

Также см. github.com/dart-lang/language/issues/731.

jamesdlin 09.04.2022 22:42

@jamesdlin Это раздражает, но приятно знать, что я не просто что-то упускаю.

Abion47 10.04.2022 00:32
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
Четыре эффективных способа центрирования блочных элементов в CSS
Четыре эффективных способа центрирования блочных элементов в CSS
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то...
0
2
18
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В основном это Вывод типа Dart List.fold против List.reduce, но в вашем случае вы можете обойти проблему, сделав свою функцию методом расширения, чтобы 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]
}

Я определенно не буду использовать расширения на этом, но полезно знать.

Abion47 10.04.2022 00:32

Другие вопросы по теме