Ada、その設計思想と言語設計を形作った言語
(iqiipi.com)- 1970年代の米国国防総省におけるソフトウェア混乱の中で誕生したAdaは、強い静的型付けと仕様-実装分離を中核とする言語である
- パッケージ構造と表現隠蔽によって完全なカプセル化を実現し、その後のJava・C#・Goなど現代言語のモジュールシステムに影響を与えた
- 意味的制約型、ジェネリック、並行性(task)、契約に基づく設計などは、Adaが数十年先んじて提示した概念であり、Haskell・Rust・Swiftなどがそれを受け継いでいる
- SPARK Adaは形式検証によってデータ競合や論理エラーまで排除し、航空・鉄道・防衛システムなどの高信頼分野で使われている
- Adaは大衆的な言語ではないが、**「静かに正しく動作する言語」**として、現代のプログラミング言語設計における根本原則を示した基盤である
Adaの誕生背景と設計哲学
- 1970年代初頭、米国国防総省(DoD) は、兵器・物流・通信システムに450以上の言語と方言が混在している状況を調査した
- 各システムは相互運用不可、保守不能、原著者不在といった問題を抱えていた
- これによりソフトウェア調達危機が発生した
- DoDは既存言語(COBOL, Fortran, PL/1など)を採用せず、5年にわたる要件定義プロセスを経た
- Strawman → Woodenman → Tinman → Ironman → Steelman 文書へと発展
- Steelman(1978)は、明示的なインターフェース分離、強い静的型付け、組み込み並行性、一貫した例外処理、機械独立性、可読性、検証可能性を要求した
- 1979年、4チーム(Green, Red, Blue, Yellow)による競争で、Jean Ichbiahが率いるGreenチームが選定され、Adaと命名された
- 名称はAda Lovelaceを記念して付けられ、言語の意図を象徴している
パッケージ構造とカプセル化
- Adaの中心構造は**パッケージ(package)**で、仕様(specification)と本体(body)が物理的に分離される
- 仕様は外部に公開される契約、本体は実装であり、コンパイラが両者の関係を強制する
- クライアントコードは、仕様にない要素へアクセスできない
- この構造はモジュールシステムの原型であり、その後の言語がこれを部分的に模倣した
- Java, Python, JavaScript, C, Go, Rustはいずれも、Adaの完全な構造的分離を実装していない
- private型は名前だけが公開され、内部表現は完全に不透明である
- クライアントは型の内部構造を知ることができず、許可された演算だけを利用できる
- これはJavaの
privateアクセス制御より強力な**表現隠蔽(representational invisibility)**である
- JavaとC#は数十年をかけて、段階的にAda水準のカプセル化へと発展してきた
型システムと意味的制約
- Adaは型とサブタイプの区別を数学的意味で定義している
- 例:
type Age is range 0 .. 150は範囲制約を持つ別個の型を生成する - 不正な型間の受け渡しはコンパイル時エラーとして検出される
- 例:
- 1983年当時、Adaの型システムはC, Fortran, Pascalよりはるかに高い表現力を持っていた
- 意味的制約型によってドメインエラーを防止する
- **判別レコード(discriminated record)**は、値によって異なるフィールドを持つ構造である
- これは現代言語の**直和型(sum type)または代数的データ型(ADT)**と同じである
- Haskell, Rust, Swift, Kotlin, TypeScriptなどが数十年後に同じ概念を導入した
ジェネリックと多相性
- Adaの**ジェネリック(generic)**は、型・値・サブプログラム・パッケージを引数に取る単位である
- コンパイル時に型検証を行う**静的多相(parametric polymorphism)**を実装する
- C++(1990), Java(2004), C#(2005), Go(2022)などは、Adaの後に数十年かけて類似機能を導入した
- Javaは**型消去(type erasure)**により、実行時の型情報が失われる
- Adaは実行時型の保持とパッケージのパラメータ化までサポートする
- Adaのジェネリックは**高階多相(higher-kinded polymorphism)**水準の表現力を提供する
- Haskellの型クラス、Rustのトレイト、C++20のconceptsに近い概念である
並行性モデルと安全性
- Adaは1983年から**言語レベルの並行性(task)**を組み込んでいた
task宣言とrendezvous通信モデルにより、共有状態のないメッセージ受け渡しを実現する- Goのchannelは同じCSP(Communicating Sequential Processes)系統の概念である
- Ada 95はprotected objectを導入した
- データアクセスを保護し、
procedure,function,entryに区分される - 自動バリア条件とロック不要の同期を提供する
- データアクセスを保護し、
- SPARK Adaは形式検証によって、データ競合、例外、範囲エラー、事前・事後条件違反が存在しないことを数学的に証明する
- Rustのborrow checkerはメモリ安全性のみを保証する一方、SPARKは論理的一貫性まで証明する
契約に基づく設計とnull安全性
- Ada 2012は**契約(contracts)**を言語に統合した
- 事前条件(precondition)、事後条件(postcondition)、**型不変条件(invariant)**を明示できる
- SPARKツールチェーンはこれを静的証明に活用する
- Eiffel(1986)のDesign by Contract概念を言語レベルで正式化した
- C++, Java, Python, Rustなどは部分的実装またはライブラリレベルの実装にとどまる
- Ada 2005は
not null型を導入し、コンパイル時のnull排除をサポートした- 既定では実行時例外(
Constraint_Error)が発生し、安全な失敗を保証する - C# 8.0のnullable referenceに近いアプローチである
- 既定では実行時例外(
例外処理構造
- Ada 83は最初期に**構造化例外処理(structured exception handling)**を導入した
- 例外は宣言してから使用し、スコープ単位で処理され、伝播規則も明確である
- Javaのchecked exceptionはAdaより発展した形で、呼び出し側が例外を明示しなければならない
- Adaは例外伝播を自由に許可する
- Rustは例外を廃し、
Result型ベースのエラー処理を採用した- Adaの貢献は、例外伝播を構造化し予測可能にした点にある
Annexと標準化構造
- Ada標準はAnnexという選択的拡張構造を持つ
- Annex C〜Hは、システム、リアルタイム、分散、数値、高信頼分野ごとの機能を定義する
- コンパイラはAnnexごとに独立認証を受けなければならない
- ACAAのACATSテストによって標準適合性を検証する
- DO-178C航空ソフトウェア認証にAdaの標準構造を直接活用できる
- C/C++でも同じ認証は可能だが、Adaのほうが構造的に適している
Adaの影響と認識の不均衡
- Adaは政府主導の言語であるため、シリコンバレー文化圏では注目されにくかった
- Cベースの簡潔な文法を好む文化との対比がある
- Adaの成功事例(航空、鉄道、防衛システム)は、失敗がないため可視性が低い
- 信頼性の高いシステムは議論や事件を生まない
- 現代言語の発展方向は、Adaがすでに示していた原則へと収束している
- 仕様-実装分離、静的型検証、言語レベル並行性、契約ベースの安全性など
- Adaは今なお航空機、鉄道、宇宙船などの高信頼システムで運用中であり、 **「静かに正しく動作する言語」**として残っている
1件のコメント
Hacker Newsのコメント
私はAdaが好きだ。だが型の話をしながら、ML系言語(ML、SML、CML、Caml、OCaml など)を完全に外しているのは驚きだった
これらの言語は構造的型付けをコンパイラレベルでサポートしている。Ada は PL/I、PHP、Perl のように言語自体が大きすぎて文法が複雑だったのが問題だった。記事ではそれを長所としているが、個人的には Annex に分離された標準拡張のほうが優れていたと思う。もしコア言語を小さくし、Annex 中心で進めていたなら、もっと広く使われていた気がする
Ada が敬遠された理由の一つは、コンパイラの価格が数万ドルだったことだ。無料やオープンソースのコンパイラがなかった時代、他の言語はただで使えた。それが決定的な要因だった
記事を読みながら Ada も記事自体も興味深かったが、いくつか事実誤認が目についた。たとえば Ada だけが実装と仕様を完全に分離すると書いていたが、JavaScript でも ES6 モジュールで private 要素を定義できる。Java の
private可視性の説明も間違っていた。こうした誤りのせいで記事の信頼性が下がってしまうprivate型を定義すると、外部から内部フィールドにアクセスできない。一方 JavaScript では、どんなオブジェクトにも自由にプロパティを追加・削除できる。つまり、Ada のコンパイル時保護の水準は JS とは比較にならないsetAccessible(true)によって String の内部を変更することさえできる記事全体は良かったが、繰り返し出てくる「言語 X ではこの機能が Ada より後になって導入された」という文が退屈だった。コード例があれば、はるかに説得力があったと思う
この Twitter アカウント は 2026 年 4 月に作られ、著者が明記されていない。短期間で驚異的な生産性を見せているが、名前を出していない点が興味深い
「すべての言語がこの20年で sum type を追加したが、Ada には最初からあった」という主張は事実だが、その起源が Ada というわけではない。Hope 言語 や NPL のほうが先だった
UNIONキーワードを提案し、その後 ALGOL 68、Hope、Miranda などで発展した。C のunionはこの概念とは異なる記事があまりにも気に入ったので AI が書いたものでなければいいと思ったが、Twitter への投稿速度が速すぎて疑わしく感じた
米空軍は当初 Ada を使う予定だったが、開発が遅れたためJOVIALを使った。私は 1981 年に JOVIAL で最初のプロジェクトを行ったが、そのとき Ada はまだ仕様策定段階だった
サイトのトップに「これは立場表明ではなく提案だ」という文句があり、それを根拠にAI が書いたサイトだと主張している
記事では「JavaScript のモジュールシステムは Ada のように型の内部表現を隠せない」と述べていたが、実際には JS モジュールでも export しなければ十分に隠せる。Ada が特別に優れている点があるのか疑問だった