名前の同等性が何であるかを正確に把握できないようです。私は構造的にダウンしていると確信しています。私の教授が挙げた例はこれでした:
Type TI=integer
Type TTI=TI
a=integer
b=TTI
f= ref float
g= ref float
aとbはどちらも構造と名前が同じですが、fとgは構造が同じです。なぜaとbが名前が同じになるのかわかりませんが、fとgはそうではありません。
タイプの同等性
代入(Cでは=で示される)などの基本的な操作の意味は、言語定義で指定されます。したがって、たとえば、次のようなステートメントの意味
x = y;
ここで、オブジェクトy
の値は、変数x
のメモリ位置にコピーされます。
ただし、割り当てなどの操作をトランスレータが受け入れるには、通常、2つのオペランドのタイプが同じである(または他の指定された方法で互換性がある)必要があります。
したがって、言語翻訳者は、場合によっては2つのタイプが等しいかどうかを判断する必要があります。ここで、2つのタイプが「等しい」(または同等である)と言うことの意味を検討します。
2つのタイプが同じであると見なされるかどうかを判断する2つの標準的な方法があります:名前の同等性および構造の同等性。
名前の同等性が最も簡単です:2つのタイプは、同じ名前である場合にのみ等しくなります。したがって、たとえば、コード内(C構文を使用)
typedef struct {
int data[100];
int count;
} Stack;
typedef struct {
int data[100];
int count;
} Set;
Stack x, y;
Set r, s;
name equivalentが言語で使用されている場合、x
とy
は同じタイプになり、r
とs
は同じタイプになりますが、タイプはx
またはy
のタイプは、r
またはs
のタイプと同等ではありません。これは、次のようなステートメントが
x = y;
r = s;
有効ですが、次のようなステートメント
x = r;
有効ではありません(つまり、翻訳者に受け入れられません)。
構造的同等性:、を使用すると、2つのタイプは、同じ「構造」を持っている場合に限り、等しくなります。さまざまな方法で解釈されます。
厳密な解釈では、2つのタイプの各コンポーネントの名前とタイプは同じである必要があり、タイプ定義で同じ順序でリストされている必要があります。
それほど厳しくない要件は、コンポーネントタイプが同じであり、2つのタイプで同じ順序である必要があることですが、コンポーネントの名前は異なる可能性があります。
上記の例をもう一度見てみると、構造的同等性を使用すると、2つのタイプStack
とSet
は同等と見なされます。つまり、翻訳者は次のようなステートメントを受け入れます。
x = r;
(C
は構造的同等性をサポートしておらず、上記の割り当てでエラーが発生することに注意してください。)
以下の2つの定義を検討してください。
type student = record
name, address : string
age : integer
type school = record
name, address : string
age : integer
x : student;
y : school;
上記の例では、変数xとyは、名前の同等性の下で異なる型を持っていると見なされます。xは1行目で宣言された型を使用します。 yは、4行目で宣言された型を使用します。名前の同等性は、プログラマーが2つの型定義を作成する場合、それらの定義はおそらく異なる型を表すことを意図しているという仮定に基づいています。 (あなたが与えた例についてはよくわかりません)
参照:プログラミング言語語用論、M.L。スコット
名前の同等性の概念は、コンパイラーが型を表すために使用する可能性のある内部データ構造を考慮する場合に最も意味があります。型がデータ構造へのポインターとして表されているとします。さらに、単純なポインター比較として型等価性チェックを実装するとします(名前の等価性など)。 integer
やfloat
のようなプリミティブ型は、有限数しかないため、一部のグローバル環境に格納されます。さらに、integer
とinteger
を比較すると、このグローバル環境のおかげで、同じ構造を指しているため、同等であることが保証されます。
ただし、ref
は型コンストラクターではなく、アトミック型ではないため、これを使用して無限に多くの型を作成できます(たとえば、ref float
、ref ref float
、等)。そのため、それらすべてをグローバル環境に保存することはできません。コンパイラがこれらの型を管理するために採用できる簡単な戦略の1つは、型コンストラクタに遭遇するたびに新しい構造を割り当てることです。その型に新しいデータ構造を割り当てます。したがって、ref float
のインスタンスは1つの新しいデータ構造になり、ref float
のもう1つのインスタンスは完全に新しい異なるデータ構造になります。ポインタの比較は失敗するため、名前が同じになることはありません。
パズルにはもう1つあります。それは、代入演算子のセマンティクスです。この型エイリアシングはコンパイラーでの単純なポインターコピーであるため、A=B
と書くと、A
は常にB
と同等の名前になります。ただし、繰り返しになりますが、F A
はF A
の別のインスタンスと同等の名前ではありません。
名前タイプの同等性では、2つの変数が同じ宣言で定義されている場合、または同じタイプ名を使用する宣言で定義されている場合、2つの変数は同じタイプになります。したがって、変数'f'
および'g'
あなたの例では同等です。ただし、変数'a'
および'b'
はタイプ名が異なるため、同等ではありません。さらに、構造タイプの同等性の下では、2つの変数が同一の構造を持っている場合、それらは同じタイプになります。したがって、変数'a'
および'b'
は同等であり、変数'f'
および'g'
は、明らかに、同じ名前の型が同じ構造を持っているため、同等です。
参照:Sebesta、プログラミング言語の概念、第10版。
aとbは同名であるため、名前が同じです。 fとgはそうではないので、名前は同じではありません。