コンテンツにスキップ

プログラミング/宣言型プログラミング

出典: フリー教科書『ウィキブックス(Wikibooks)』

宣言型プログラミングとは

[編集]

宣言型プログラミングは、「何を」行うかを記述し、「どのように」行うかの詳細な制御を言語や環境に委ねるプログラミングパラダイムです。命令型プログラミングとは対照的に、プログラムの論理的な構造や期待する結果に焦点を当てます。

宣言型プログラミングの主要な特徴

[編集]
  • 結果志向のアプローチ
  • 状態変更の最小化
  • 高レベルな抽象化
  • コードの読みやすさと簡潔さ

宣言型プログラミングのパラダイム

[編集]

関数型プログラミング

[編集]

関数型プログラミングは宣言型アプローチの代表的な形態です。

Haskell による純粋関数の例

[編集]
-- リストの変換と集計を宣言的に記述
processNumbers :: [Int] -> [Int]
processNumbers numbers = 
    numbers
    |> filter even  -- 偶数のみを選択
    |> map (*2)     -- 各要素を2倍
    |> takeWhile (< 100)  -- 100未満の要素のみ取得

Scala による関数型アプローチ

[編集]
object DeclarativeFunctions {
  // 宣言的なデータ変換
  def processData(data: List[Int]): List[Int] = {
    data
      .filter(_ % 2 == 0)      // 偶数のフィルタリング
      .map(_ * 2)              // 各要素の2倍
      .takeWhile(_ < 100)      // 条件に合う要素のみ抽出
  }

  // パターンマッチングを利用した宣言的な関数
  def describe(value: Any): String = value match {
    case n: Int if n > 0 => "Positive Integer"
    case n: Int if n < 0 => "Negative Integer"
    case 0 => "Zero"
    case _ => "Not a number"
  }
}

SQL (宣言型クエリ言語)

[編集]

SQLは宣言型言語の最も顕著な例の一つです。

PostgreSQL での宣言的データ操作

[編集]
-- 宣言的にデータを抽出・変換
WITH sales_summary AS (
    SELECT 
        department,
        SUM(revenue) as total_revenue,
        AVG(revenue) as avg_revenue
    FROM sales_data
    WHERE date BETWEEN '2023-01-01' AND '2023-12-31'
    GROUP BY department
    HAVING SUM(revenue) > 1000000
)
SELECT 
    department, 
    total_revenue, 
    avg_revenue
FROM sales_summary
ORDER BY total_revenue DESC;

リアクティブプログラミング

[編集]

リアクティブプログラミングは、データストリームと変更の伝播に焦点を当てた宣言型アプローチです。

RxJS (JavaScript) による例

[編集]
import { from } from 'rxjs';
import { filter, map, reduce } from 'rxjs/operators';

const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

from(numbers)
  .pipe(
    // 宣言的な変換
    filter(n => n % 2 === 0),     // 偶数のみ
    map(n => n * n),               // 二乗
    reduce((acc, curr) => acc + curr, 0)  // 合計
  )
  .subscribe(result => {
    console.log(result);  // 偶数の二乗の合計
  });

XQuery (宣言的XML処理)

[編集]
(: XMLデータの宣言的な変換と抽出 :)
let $books := doc("books.xml")/bookstore/book
return 
  <result>
    {
      for $book in $books
      where $book/price < 30
      order by $book/title
      return 
        <affordable-book>
          <title>{$book/title/text()}</title>
          <price>{$book/price/text()}</price>
        </affordable-book>
    }
  </result>

Prolog (論理型プログラミング) =

[編集]
% 家族関係の宣言的定義
parent(john, mary).
parent(john, tom).
parent(mary, alice).

% 祖父母関係の宣言的な推論規則
grandparent(X, Z) :- 
    parent(X, Y), 
    parent(Y, Z).

% クエリ例
% ?- grandparent(john, alice).  % trueを返す

宣言型プログラミングの利点

[編集]
  1. コードの簡潔さと読みやすさ
  2. 並列処理や最適化の容易さ
  3. エラーの削減
  4. 高レベルな抽象化

注意点と限界

[編集]
  1. すべての問題に適しているわけではない
  2. パフォーマンス面での潜在的なオーバーヘッド
  3. 低レベルな制御の難しさ
  4. 学習曲線が急な場合がある

実践的なヒント

[編集]
  1. 問題の本質に集中する
  2. 副作用を最小限に抑える
  3. 関数の純粋性を保つ
  4. コンポーザブルな関数を設計する

まとめ

[編集]

宣言型プログラミングは、プログラマーに「何を」行うかを明確に表現する力を与えます。これは、より抽象的で柔軟なコーディングアプローチであり、複雑なシステムをよりシンプルに表現するための強力な手法です。