動的型付け
型システム |
---|
主要カテゴリ |
静的型付け vs 動的型付け 強い vs 弱い 明示的 vs 型推論 名前的 vs 構造的 ダックタイピング |
マイナーカテゴリ |
部分型 再帰型 部分構造型 依存型 漸進的型付け フロータイピング 潜在的型付け |
型理論のコンセプト |
直積型 - 直和型 交差型 - 共用型 単一型 - 選択型 帰納型 - 精製型 トップ型 - ボトム型 函数型 - 商型 全称型 - 存在型 一意型 - 線形型 |
動的型付け(どうてきかたづけ、英: Dynamic typing)とは、値やオブジェクトの型安全性を、実行時に検証するというコンピュータプログラミングの型システムの方法である。型の検査は実行時のプロセス上で行われて、ランタイムシステムの実行時型情報(RTTI)が照会されるなどして解析される。
動的な型チェックは、代入、束縛、関数適用、ダウンキャスト、ディスパッチ、バインディングといった所で行われる。なお、コンパイル時やインタプリタ開始時の最適化によってすでに型安全性が保証されている所は省略される。動的型付けの言語では、引数や返り値や変数宣言への型注釈が省略されやすくなる。
対義語は静的型付けであり、こちらでは値やオブジェクトの型安全性をコンパイル時に検証する。型の検査はソースコードの解析によって行われる。
概要
[編集]動的型付けのルーツはLISPにさかのぼる。LISPは、同時期のFORTRANやCOBOLとは一線を画した、計算モデル(ラムダ計算)を裏付けに持つ言語であった。しかし型付きラムダ計算ではなく、実行前に型チェックが行われることもなく、型エラーはその式が評価(実行)されるまでわからないという欠点、すなわち動的型付き言語特有の欠点を持つ初期の言語である。その後、LOGOを経て、動的な型という概念を明確にしたのがSmalltalkである[1]。そして、このような性質の言語を動的型付き言語(どうてきかたつきげんご、英: dynamically-typed languages)という。
オブジェクト指向にもとづく Smalltalk では、すべての処理対象は何らかのクラスに属すため、型という概念そのものは存在する。しかし Smalltalk では、
- すべてのクラスはルートクラスである Object に由来するので、最低限 Object としての振る舞いが保証される。
- たとえ同一の機能名を持っていても、実際に起こる結果はクラスによって異なるかもしれない。
- クラス(型)自体も一種のオブジェクトであり、必要ならクラスに関するメタプログラミングが行える。
などの特徴を持ち、型よりもむしろ「特定の名称のメソッドを受け付けるべき」「メソッドはその名前に見合った動作を行うべき」というプロトコル[2]的な立場による疎結合の信頼性を重視している。このプロトコル的な信頼性こそが動的型付けの要である。これを積極的に行うのがダック・タイピングである。
両者の違いは、静的は予防的な立場であり、動的は自浄的な立場といえるだろう。
通常、静的型付けはオペレーティングシステムやシステムプログラムのような大規模で厳密性が要求される領域に適合するといわれている。その反面、最初の型定義を誤ると一部分の影響が全体に波及すること、また柔軟性に乏しくわずかな変換に手間のかかる経路を用意したり同じような機能を型別に実装しなければならないことなど、いわばお役所仕事的な煩雑さを伴うという弱点を持つ。この煩雑さは IDE によるリファクタリングの支援によって軽減され得る。なお近年[いつ?]の研究により、静的型付き言語も文脈から型を推論する型推論能力を持つなど、簡略化の方向へ向かってはいる。
一方、動的型付き言語ではそもそも対象に特定の構造を期待しないため、変更への対応は柔軟である。特に配列、辞書、集合といったコレクションの利便性が顕著で、そのため近年[いつ?]いわゆるスクリプト言語や動的プログラミング言語は多くが動的型付けを採用している。動的型付けの難点である最適化の弱さは、コンピューターの能力が増すことで相対的に小さな問題になっており、スクリプト言語を中心に今後も動的型付けは発展するものと思われる[3]。
静的型付けとの比較
[編集]静的型付けは、
- 機能(関数)が形式に合った正しい型のデータのみを処理することを事前の検査により保証する
- この保証があるため、高度な最適化が可能である
と主張される。この方向性に基づき、全ての機能と変数において処理する対象の型をプログラムの定義時点で決定し、型が異なるデータを受け付けない(あるいは上位互換の型に限定する)。MLなどでは型に従わない式は許されない。Javaなどでは明示的にキャストする必要があり、キャストは実行時に検査される。Cなどではキャストを正しく使うのはプログラマの責任であり、通常のコンパイラは特にチェックなどを入れず書かれた通りのコードを吐く。
これに対し、動的型付けでは、定義では型の限定を行わず、実行時に合致するデータが渡されると期待する、または合致するデータであるかを判定する。期待する型とは異なるデータが渡された場合、単にエラーとするものもあれば、型変換ないし強制(coerce、数値を文字列にしたりするような変換)したり、場合によっては委譲といったプロトコルに従うものもある。
例えば、Perl, Pythonで共に実行可能(文法エラーとはならない)な下記のコードにおいて、Perlでは20と表示される一方、Pythonでは実行時にTypeError例外が発生する。なおこの2種類を「強い動的型付け」「弱い動的型付け」と区別するのは間違いである(どちらも、プログラムが異常なまま走り続けることは無いので、強い型付けである)。
print('10'+10);
プログラムの最適化手法のうち、静的型付けでは容易だが動的型付けでは難しいものがあり、動的型付けが不利とされる理由のひとつになっている。