Menu
Coddy logo textTech

Patterns & Matching (3.0)

Part of the Object Oriented Programming section of Coddy's Dart journey — lesson 87 of 110.

Dart 3 introduced pattern matching, a powerful way to destructure and inspect data in a single expression. Patterns let you extract values from objects, check their structure, and bind variables - all at once.

You've already seen basic destructuring with records. Patterns extend this to work with objects, lists, and maps:

void main() {
  // List patterns
  var numbers = [1, 2, 3];
  var [a, b, c] = numbers;
  print('$a, $b, $c');  // 1, 2, 3
  
  // Map patterns
  var user = {'name': 'Alice', 'age': 30};
  var {'name': name, 'age': age} = user;
  print('$name is $age');  // Alice is 30
}

Patterns become especially powerful in switch expressions. You can match on type, value, and structure simultaneously:

String describe(Object obj) {
  return switch (obj) {
    int n when n < 0 => 'Negative number',
    int n => 'Positive number: $n',
    String s => 'String of length ${s.length}',
    [int first, ...] => 'List starting with $first',
    _ => 'Something else',
  };
}

void main() {
  print(describe(-5));        // Negative number
  print(describe(42));        // Positive number: 42
  print(describe([1, 2, 3])); // List starting with 1
}

The when clause adds conditions to patterns, and ... matches remaining elements in a list. The underscore _ acts as a wildcard that matches anything. Combined with sealed classes, patterns enable exhaustive, type-safe handling of complex data structures.

challenge icon

Challenge

Easy

Let's build a data classifier that uses pattern matching to analyze and categorize different types of input! You'll create a system that can identify and describe various data structures using Dart 3's powerful pattern matching features.

You'll organize your code into two files:

  • classifier.dart: Create a function called classify that takes an Object parameter and returns a String description. Use a switch expression with pattern matching to handle these cases:
    • An empty list [] should return Empty list
    • A list with exactly one integer element should return Single item: [value]
    • A list with exactly two elements should return Pair: [first] and [second]
    • A list starting with an integer followed by more elements should return List starting with [first], length: [total length] (use the ... rest pattern)
    • A map containing both 'name' and 'age' keys should return [name] is [age] years old (use map pattern destructuring)
    • An integer that is negative (use when clause) should return Negative: [value]
    • An integer that is zero should return Zero
    • Any other integer should return Positive: [value]
    • Any other value should return Unknown type
  • main.dart: Import your classifier and demonstrate pattern matching with various inputs. Print the result of classifying each of these values:
    • An empty list []
    • A list with one element: [42]
    • A list with two elements: ['hello', 'world']
    • A longer list: [1, 2, 3, 4, 5]
    • A map: {'name': 'Alice', 'age': 25}
    • The integer -10
    • The integer 0
    • The integer 99

This challenge combines list patterns, map patterns, the when clause for guards, and the rest pattern (...) - all the key pattern matching features from the lesson!

Expected output:

Empty list
Single item: 42
Pair: hello and world
List starting with 1, length: 5
Alice is 25 years old
Negative: -10
Zero
Positive: 99

Cheat sheet

Dart 3 introduced pattern matching for destructuring and inspecting data in a single expression.

List Patterns

Extract values from lists:

var numbers = [1, 2, 3];
var [a, b, c] = numbers;
print('$a, $b, $c');  // 1, 2, 3

Map Patterns

Destructure maps by key:

var user = {'name': 'Alice', 'age': 30};
var {'name': name, 'age': age} = user;
print('$name is $age');  // Alice is 30

Switch Expressions with Patterns

Match on type, value, and structure:

String describe(Object obj) {
  return switch (obj) {
    int n when n < 0 => 'Negative number',
    int n => 'Positive number: $n',
    String s => 'String of length ${s.length}',
    [int first, ...] => 'List starting with $first',
    _ => 'Something else',
  };
}

Pattern Features

  • when clause: Adds conditions to patterns
  • ... (rest pattern): Matches remaining elements in a list
  • _ (wildcard): Matches anything

Try it yourself

import 'classifier.dart';

void main() {
  // TODO: Use the classify function to categorize each value
  // and print the results
  
  // Test with an empty list
  print(classify([]));
  
  // TODO: Test with a list containing one element: [42]
  
  // TODO: Test with a list containing two elements: ['hello', 'world']
  
  // TODO: Test with a longer list: [1, 2, 3, 4, 5]
  
  // TODO: Test with a map: {'name': 'Alice', 'age': 25}
  
  // TODO: Test with the integer -10
  
  // TODO: Test with the integer 0
  
  // TODO: Test with the integer 99
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming