Menu
Coddy logo textTech

クロージャの理解

CoddyのDartジャーニー「論理とフロー」セクションの一部 — レッスン 46/65。

クロージャは、作成された場所の変数を、その元のコンテキストの実行が終了した後でも「覚えている」特殊な種類の関数です。どこへ行くときでも、生まれた場所の一部を持ち運ぶ関数だと考えてみてください。

ある関数の内部に別の関数を作成すると、内側の関数は外側の関数の変数にアクセスできます。これをクロージャたらしめているのは、外側の関数の実行が完了した後でも、このアクセスが持続するという点です。

Function createGreeting(String name) {
  return () {
    return "Hello, $name!";
  };
}

この例では、createGreeting によって返される無名関数はクロージャです。これは、その周囲のスコープから name パラメータをキャプチャします。createGreeting の実行が終了した後でも、返された関数は name が何であったかを覚えています。

クロージャは、特化した関数を作成したり、クリーンな方法で状態を保持したりするのに非常に便利です。これらを使用すると、作成された環境に基づいてカスタマイズされた関数を構築でき、コードをより柔軟で強力なものにすることができます。

challenge icon

チャレンジ

簡単

パーソナライズされたメッセージ生成システムを構築することで、クロージャを実演するプログラムを作成してください。このプログラムは、特定の情報を「記憶」し、元のコンテキストが終了した後でもその情報を使用してカスタマイズされたメッセージを生成する関数を作成します。

  1. 個人の名前を表す文字列入力を読み取ります
  2. 挨拶のタイプ("formal""casual"、または "friendly")を表す文字列入力を読み取ります
  3. 会社名を表す文字列入力を読み取ります
  4. 名前と挨拶のタイプをパラメータとして受け取る createMessageGenerator という関数を作成します
  5. createMessageGenerator 関数は、以下の処理を行う別の関数(クロージャ)を返す必要があります:
    • 会社名をパラメータとして受け取ります
    • 外部関数のスコープにある名前と挨拶のタイプを使用します
    • 挨拶のタイプに基づいてフォーマットされたメッセージを返します:
      • "formal" の場合: "Dear [name], we are pleased to welcome you to [company]."
      • "casual" の場合: "Hey [name]! Welcome to [company]!"
      • "friendly" の場合: "Hi [name], so glad you joined [company]!"
  6. 名前と挨拶のタイプの入力を使用して createMessageGenerator 関数を呼び出し、クロージャ関数を取得します
  7. 返されたクロージャ関数を会社名の入力で呼び出し、メッセージを生成します
  8. 以下の正確な形式で結果を表示します

例えば、入力が "Alice""formal""TechCorp" の場合、プログラムは次のように出力する必要があります:

Message Generator System
========================
Creating message generator for: Alice
Greeting type: formal
Company: TechCorp
========================
Generated message: Dear Alice, we are pleased to welcome you to TechCorp.
Message generation completed successfully

入力が "Bob""casual""StartupXYZ" の場合、プログラムは次のように出力する必要があります:

Message Generator System
========================
Creating message generator for: Bob
Greeting type: casual
Company: StartupXYZ
========================
Generated message: Hey Bob! Welcome to StartupXYZ!
Message generation completed successfully

入力が "Carol""friendly""InnovateLab" の場合、プログラムは次のように出力する必要があります:

Message Generator System
========================
Creating message generator for: Carol
Greeting type: friendly
Company: InnovateLab
========================
Generated message: Hi Carol, so glad you joined InnovateLab!
Message generation completed successfully

プログラムは、別の関数を返す関数を作成することによってクロージャを実演する必要があります。返された関数(クロージャ)は、外部関数が実行を終了した後でも、外部関数のスコープからの変数(名前と挨拶のタイプ)にアクセスできる必要があります。条件文を使用して、入力された挨拶のタイプに基づいた適切なメッセージ形式を決定してください。

チートシート

クロージャとは、作成された場所の変数を、その元のコンテキストが実行を終了した後でも「覚えている」関数のことです。

ある関数の内部で別の関数を作成すると、内側の関数は外側の関数の変数にアクセスできます。このアクセスは、外側の関数が実行を完了した後でも持続します。

Function createGreeting(String name) {
  return () {
    return "Hello, $name!";
  };
}

この例では、createGreeting によって返される無名関数がクロージャです。これは、周囲のスコープから name パラメータをキャプチャします。createGreeting の実行が終了した後でも、返された関数は name が何であったかを覚えています。

クロージャは、特化した関数を作成したり、クリーンな方法で状態を維持したりするのに役立ちます。クロージャを使用すると、作成された環境に基づいてカスタマイズされた関数を構築できます。

自分で試してみよう

import 'dart:io';

void main() {
  // 入力を読み込む
  String? name = stdin.readLineSync();
  String? greetingType = stdin.readLineSync();
  String? company = stdin.readLineSync();
  
  // システムヘッダーを表示
  print("Message Generator System");
  print("========================");
  print("Creating message generator for: $name");
  print("Greeting type: $greetingType");
  print("Company: $company");
  print("========================");
  
  // TODO: 以下にコードを記述してください
  // クロージャを返す createMessageGenerator 関数を作成してください
  // 関数を呼び出してメッセージを生成してください
  
  // 最終結果を出力
  print("Generated message: \$message");
  print("Message generation completed successfully");
}
quiz icon腕試し

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

論理とフローのすべてのレッスン