Software Engineering Lecture 5/16
Menu Menu
先週の復習
- プログラミングの規則
- Perl の構文
型 type
型は、プログラミングの理論では重要な概念である。より実用的に使われている方法は、型を使った検査である。これは、プログラムが「正しい」ことを保証するものではないが、ある決まった範囲内での整合性を保証する。
プログラミング言語は、変数などに格納できる値の形式が決まっているのが普通である。その基本的な形を組み合わせることにより、より複雑なデータ構造を作ることができる。例えば、Perl では、
整数 32bit 小数 double 64bit 文字列 "abcd" 真理値が基本的なデータ構造であり、これが型を構成している。これらを組み合わせたものとして、
配列 $array[5] 連想配列 $array{'a'}などがある。Perlでは、データ構造はObjectを定義することや、TIEと呼ばれる連想配列の機能の拡張によりさらに拡張可能である。(型とObjectにどういう関係があるかは、まだ研究途中の話題である)
型は集合ととらえることもできる。あるいは、入力が、その範囲を満たすと言う論理式だと考えることもできる。後者のようにとらえると、Hoare logicのpre condtion/post conditionとして型を使うこともできる。こうすると、プログラムの値を問題にしないので、Hoare logicの検証は簡単になり、実際にコンパイル時にチェックすることが可能になる。
型には包含関係がある。例えば、整数は 小数の部分集合である。もちろん、整数の配列は、小数の配列の部分集合である。包含される型からの包含する型への代入は安全であるが逆は危険である。
代入や関数の値を渡す時に、型の変換をおこなうことができるが、この時に、その変換が正当なものかを調べることがおこなわれる。より大きな集合に変換する場合をup cast、より小さい集合に変換する場合をdown cast という。down cast では情報が失われる可能性がある。(だから、down castに文句をいうたこなコンパイラも存在するようだ)
classで作ったデータの型の包含関係はさらに複雑になる。この複雑な関係を調べたり、どうやって作りあげていくかを調べることが、オブジェクト指向設計の重要な役目の一つである。
Perlでは、型付けは非常に弱く、積極的に型変換が行なわれる。これは、便利な一方で、間違いの元になりやすいので注意を要する。一般に、強い型付けの言語は、時間がかかるが安全性の高いプログラミングを提供し、弱い型付けの言語は速いが安全性の低いプログラミングを提供する。
問題
C言語で以下の型は何を表すのか。日本語または英語で説明せよ。また、その型をtypedefで宣言する例題を作れ。- char *
- int *(float,char *)
- int (*[])()
C言語で以下の型が整合するように、タイプ変数A,B,Cに適合する型を決めよ。
4 | char * | char A |
5 | int *(float,char *) | A (float,char *) |
6 | int (*[])() | B [] |
7 | int (*)() | B * |
8 | A (A *, char *) | (B *) (B ** ,C) |
ヒント : 構文木を書けば簡単。
型の整合性の検査
型の整合性の検査には、Unification (単一化)という方法が知られている。この方法では特に、一部に不定の型があった時に、その型に関する特殊化の度合いも知ることができる。不定の型は「タイプ変数」とも呼ばれる。C++ ではテンプレートと呼ばれる機能により限られた意味でのタイプ変数を使うことができる。MLと呼ばれる言語では、タイプ変数と型の単一化が積極的に使われており効果を挙げている。MLは計算理論のグループの間では良く使われている。
型 type の表現
原子タイプ int char long float double 合成 (積) C の struct complex : double double; 合成 (和) c の union number : int | float | double ; 関数 add : int int -> int | float float -> float | double double -> double ;ポインタを型で取り扱うには、少し工夫が必要。
関数の定義の和は、polymorphic function (多相関数) と呼ばれる。入力したデータの型によって関数の振るまいが異なる。C++ は、polymorhic function がある。Perl も、多少、そういう所がある。
型変数とテンプレート
複素数を表すのは、二つの実数。その実数は、int でも double でも float でも良い。上の方法では、
complex_double : double double; complex_int : int int; complex_float : float float;ということになる。これは、少し不便。そこで、
complex<FLT> : FLT FLT;として、
complex<double> complex<int> complex<float>みたいに扱えると便利だろう。
C++ の complex
g++ の complex の実装を調べてみよう。Generic Programming
型変数を含む一般的な型整合
int -> Vと
V1 -> floatを型整合させると、
V = float V1 = int int -> floatと言う結果が得られる。
問題
以下の型整合を計算せよ。(1)
int float -> double int V1 -> V2(2)
V1 float -> V1 int V1 -> V1(3)
V V -> V1 V -> int
オブジェクトと型
オブジェクトって、何?
Perl の Math::Comlex を使ってみよう。
宿題
以上は宿題とします。宿題は、メールでSubjectをSubject: Report on Software Engineering Lecture 5/16として提出すること。この講義の問題を提出する時には、
Subject: Practice on Software Engineering Lecture 5/16とすること。