Menu
Coddy logo textTech

パターンとマッチング (3.0)

CoddyのDartジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 87/110。

Dart 3では、単一の式でデータを構造分解して検査するための強力な手法であるパターンマッチングが導入されました。パターンを使用すると、オブジェクトからの値の抽出、構造のチェック、変数のバインドをすべて一度に行うことができます。

レコードによる基本的な分割代入については、すでに学習しました。パターンはこれを拡張し、オブジェクト、リスト、マップでも動作するようにします:

void main() {
  // リストのパターン
  var numbers = [1, 2, 3];
  var [a, b, c] = numbers;
  print('$a, $b, $c');  // 1, 2, 3
  
  // マップのパターン
  var user = {'name': 'Alice', 'age': 30};
  var {'name': name, 'age': age} = user;
  print('$name is $age');  // Alice is 30
}

パターンは、switch 式において特に強力になります。型、値、構造を同時にマッチさせることができます。

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));        // 負の数
  print(describe(42));        // 正の数: 42
  print(describe([1, 2, 3])); // 1で始まるリスト
}

when 句はパターンに条件を追加し、... はリスト内の残りの要素に一致します。アンダースコア _ は、あらゆるものに一致するワイルドカードとして機能します。シールドクラスと組み合わせることで、パターンは複雑なデータ構造の網羅的で型安全な処理を可能にします。

challenge icon

チャレンジ

簡単

パターンマッチングを使用して、さまざまな種類の入力を分析および分類するデータ分類器を作成しましょう!Dart 3の強力なパターンマッチング機能を使用して、さまざまなデータ構造を識別し、説明するシステムを作成します。

コードを2つのファイルに整理します:

  • classifier.dart: Object型のパラメータを受け取り、String型の説明を返すclassifyという関数を作成します。パターンマッチングを備えたswitch式を使用して、以下のケースを処理します:
    • 空のリスト []Empty list を返す必要があります
    • 整数要素が1つだけのリストは Single item: [value] を返す必要があります
    • 要素がちょうど2つのリストは Pair: [first] and [second] を返す必要があります
    • 整数で始まり、その後にさらに要素が続くリストは List starting with [first], length: [total length] を返す必要があります(... レストパターンを使用してください)
    • 'name''age' の両方のキーを含むマップは [name] is [age] years old を返す必要があります(マップパターンの非構造化を使用してください)
    • 負の整数(when 句を使用)は Negative: [value] を返す必要があります
    • 0である整数は Zero を返す必要があります
    • その他の整数は Positive: [value] を返す必要があります
    • その他の値は Unknown type を返す必要があります
  • main.dart: 分類器をインポートし、さまざまな入力でパターンマッチングを実演します。以下の各値を分類した結果を出力してください:
    • 空のリスト []
    • 要素が1つのリスト:[42]
    • 要素が2つのリスト:['hello', 'world']
    • より長いリスト:[1, 2, 3, 4, 5]
    • マップ:{'name': 'Alice', 'age': 25}
    • 整数 -10
    • 整数 0
    • 整数 99

このチャレンジでは、リストパターン、マップパターン、ガードのための when 句、およびレストパターン(...)を組み合わせます。これらはすべてレッスンで学んだ主要なパターンマッチング機能です!

期待される出力:

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

チートシート

Dart 3では、単一の式でデータのデストラクト(構造分解)と検査を行うためのパターンマッチングが導入されました。

リストパターン

リストから値を抽出します:

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

マップパターン

キーによってマップをデストラクトします:

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

パターンを使用したSwitch式

型、値、および構造に基づいてマッチングを行います:

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',
  };
}

パターンの機能

  • when 句: パターンに条件を追加します
  • ... (レストパターン): リスト内の残りの要素にマッチします
  • _ (ワイルドカード): あらゆるものにマッチします

自分で試してみよう

import 'classifier.dart';

void main() {
  // TODO: classify 関数を使用して各値を分類する
  // そして結果をプリントする
  
  // 空のリストでテストする
  print(classify([]));
  
  // TODO: 1つの要素を含むリストでテストする: [42]
  
  // TODO: 2つの要素を含むリストでテストする: ['hello', 'world']
  
  // TODO: より長いリストでテストする: [1, 2, 3, 4, 5]
  
  // TODO: マップでテストする: {'name': 'Alice', 'age': 25}
  
  // TODO: 整数 -10 でテストする
  
  // TODO: 整数 0 でテストする
  
  // TODO: 整数 99 でテストする
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン