Pattern Matching

dart

Возможность сопоставлять значение с шаблоном. Не просто проверка на строгое равенство по значению, но и проверка соответствия по форме.
Применяется в основном с switch case и if case.

При простом сравнении значений, может показаться что ничего необычного, просто проверка на равенство как в JavaScript.

  // Привычное по JavaScript поведение switch, когда значение == значению кейса
  switch (number) {
    // Константный паттерн, если number == 42
    case 42:
      print('Answer 42');
  }

Но возможно и более сложное сопоставление, которое рекурсивно сопоставляет сложные структуры:

  var obj1 = ['a', 'b'];

  switch (obj1) {
    // Не этот кейс. Оба элемента строки, но порядок другой.
    case ['b', 'a']:
      print('Case 1');
    // Не этот кейс. Первый элемент подходит, а второй не строка
    case ['a', 42]:
      print('Case 2');
    // Выполнение будет данного кейса. obj список с двумя строками, и именно в таком порядке
    case ['a', 'b']:
      print('Case 3'); // Case 3
  }

Сопоставляемые части можно опускать с помощью _ и ...:

  var obj2 = ['a', 'b'];

  switch (obj2) {
    // С помощью заполнителя _ (wildcard) мы игнорируем первое значение в списке, говорим что оно не важно.
    // Выполниться этот кейс, так как второе значение подходит
    case [_, 'b']:
      print('Case 1'); // Case 1
    // Подходит и этот кейс, но switch выполняет первый подходящий по порядку
    case ['a', 'b']:
      print('Case 2');
  }

Проверять можно не только соответствие конкретным значениям в структурах, но и типам и условиям:

  var obj3 = const ['a', 42];

  switch (obj3) {
    // Выполниться этот кейс, так как первое значение строка, а вторая целое число,
    case [String _, int _]:
      print('Case 1'); // Case 1
    // Этот кейс тоже подходит, первое значение строка, а второе 7 или 42. Но первый кейс подошёл первым
    case [String _, 7 || 42]:
      print('Case 2');
  }

С объектами:

switch (shape) {
  // Проверяем что тип объекта соответствует Rect, а затем свойства объекта.
  case Rect(width: var w, height: var h): // ...
}