1. Именованный тип эквивалентен сам себе.
2. Если тип T=tid(I,B) имеет описание declared(I,B,T1), где T1 – именованный тип, то типы T и T1 эквивалентны.
Это очень ограничительное определение. Даже в Паскале допустимо присваивание
U:=V,
если переменные U и V описаны как
var U,V: array[1..10]of real,
хотя имеют неименованный тип "массив". Но в том же Паскале этот оператор недопустим из-за неэквивалентности типов переменных, если они описаны как
var U: array[1..10]of real;
var V: array[1..10]of real;
Чтобы охватить все эти случаи, компилятор для каждого вхождения выражения типа, начинающегося с array, record или ^ (т.е. не являющегося идентификатором типа), вводит уникальное имя типа – псевдоним, благодаря чему разные вхождения одного и того же выражения типа оказываются неэквивалентными в смысле именной эквивалентности.
В соответствии со сказанным следует внести изменения в правила DC-грамматики для нетерминала type, определяющие атрибут типа. В них включается теперь порождение и описание псевдонимов типа. Для генерации новых "имен" можно использовать самые разные методы; мы здесь воспользуемся предикатом recorda, генерирующем в качестве псевдонима уникальную ссылку на пустой терм, записываемый по ключу alias. описание этого псевдонима типа включается в виде предиката declared.
type(B,tid(A,B)) -->
[array,`[,n(M),`:,n(N),`],of],type(B,T),
{recorda(alias,_,A),
assert(declared(A,B,type(arr(M,N,T)))}.
type(B,tid(A,B)) -->
[record],field(B,F),fields(B,LF),
{correct(F,LF),
recorda(alias,_,A),
assert(declared(A,B,type(rec([F|LF])))},
[end].
type(B,tid(A,B)) -->
[`^,id(I)],
{(type_id2(I,B,B1,type(_));
assert(declared(I,B,type(referred))),
B1=B),
recorda(alias,_,A),
assert(declared(A,B,type(ref(I,B1)))}.
Предикат consist в этом случае определяется следующим образом:
consist(T1,T2):T1=int,T2=real ; % приводимость
equiv(T1,T2) ; % эквивалентность
error("Несовместимые типы").
equiv(T,T).
equiv(tid(I,B),tid(I1,B1)):declared(I,B,type(tid(I1,B1)));
declared(I1,B1,type(tid(I,B))).
Именная эквивалентность сравнительно просто реализуется. Но это – отношение (рефлексивное и симметричное) не транзитивно, и поэтому не является эквивалентностью ни в математическом, ни в привычном, обыденном смысле. Понятие псевдонима типа обычно не даётся программистам, Поэтому начинающие программисты на Паскале часто делают ошибки, вроде указанных в примере. Мотивацией для введения именной эквивалентности в 1970-е годы послужило желание избежать ошибок программирования, вроде присваивания "яблокам" "крабов", когда и те, и другие описаны как целые. С развитием объектно-ориентированного программирования подобные ухищрения стали излишними, а именная эквивалентность осталась в некоторых языках как анахронизм.
Структурно-именная эквивалентность
Этот тип эквивалентности самый простой: эквивалентными считаются типы, имеющие одинаковый базовый тип. Предикат consist в этом случае определяется следующим образом:
consist(T1,T2):base_type(T1,BT1),base_type(T2,BT2),
(BT1=int,BT2=real ; % приводимость
BT1=BT2 ; % эквивалентность
error("Несовместимые типы")).
При этом нет необходимости вводить псевдонимы типа, как в случае именной эквивалентности. Вместо предиката acc_type при анализе доступа можно применять предикат base_type.
Отношение структурно-именной эквивалентности рефлексивно, симметрично и транзитивно. По вложению оно лежит строго между структурной и именной эквивалентностями. Им легко пользоваться на практике.
Примеры
1.
С помощью несложной программы мы сможем узнать внутренний код произвольного символа.
Program Code_pf_Char;
{Программа читает символ с клавиатуры и выводит на экран
этот символ и соответствующий ему внутренний код}
var
ch: Char; {В эту переменную читается символ}
begin
Write('Введите любой символ: ');
ReadLn(ch); {Читаем один символ}
WriteLn(ch, ' = ',ord(ch)); {Преобразуем его к целому и выводим на экран}
END.
Обращаем внимание: при вызове
WriteLntch,' = ',ord(ch));
третьим параметром обращения указан вызов функции ORD (СН) , что с точки зрения языка является выражением; во многих случаях при вызове процедур и функций в качестве параметров вызова можно указывать не только переменные или константы, но и выражения с их участием.
2.
Давайте посмотрим, как можно реализовать на универсальном языке программирования простейшие инструкции лингвиста (даже не используюшие этих понятий), касающиеся этапа преобразования орфографического текста в фонетическую транскрипцию. Далее приведен пример задачи и ее решения на языке Паскаль.
Непроизносимые гласные:
Сочетания "вств" и "стн" транскрибируются как [ств] и [сн] соответственно, т. е.:
1) /вств/ -> [ств]
2) /стн/ -> [лнц]
Реализация двух данных правил на языке Паскаль:
program transcription;
var
Word: String;
I, J, K: Integer;
begin
Write('Введите слово: '); ReadLn(Word);
K := Pos('вств', word);
while (K 0) do
begin
delete(Word, K, 1);
K := Pos('вств', Word);
end;
K := Pos('стн', Word);
while (K 0) do
begin
delete(Word, K+1, 1);
K := Pos('стн', Word);
end;
WriteLn('Транскрипция: ', Word);
end.
Как видно из примера, два правила, изложенные в лингвистическом описании, реализуются программой в двадцать с лишним строк. Нетрудно заметить, что а) такая запись очень громоздка, б) она трудна для восприятия, в) она совершенно не имеет ничего общего с записью, естественной для лингвиста и поэтому плохо отражает суть происходящих преобразований. А если бы мы чуть-чуть усложнили правила, введя несколько слов-исключений, требуя проверить, не является ли транскрибируемое слово производным от одного из них, программа увеличилась бы в два раза или бол
... и в то же время мощного математического аппарата, опирающегося главным образом на теорию множеств и математическую логику и обеспечивающего теоретический базис реляционного подхода к организации баз данных; 3. возможность ненавигационного манипулирования данными без необходимости знания конкретной физической организации баз данных во внешней памяти. Однако реляционные системы далеко не ...
... Эти три проблемы осложняют использование BCB dll из приложений, созданных на VC, но все-таки это возможно. Ниже описаны три способа создания dll совместимой с VC и дальнейшего успешного использования этой dll. Алгоритмы создания VC-совместимой dll и ее использование Два из описанных в этом разделе алгоритмов применяют неявное связывание с dll, один – явную загрузку dll. Опишем сначала самый ...
... фактически игнорирует это указание: “упаковка” данных в Object Pascal осуществляется автоматачески везде, где это возможно. 1.2.1 Массивы Массивы в Object Pascal во многом схожи с аналогичными типами данных в других языках программирования. Отличительная особенность массивов заключается в том, что все их компоненты суть данные одного типа (возможно, структурированного). Эти компоненты можно ...
... поставленной задачи показала правильность выбранного подхода. Тем не менее, работа требует дальнейше доработаки для организации постоянного доступа читателей к библиографическим ресурсам библиотекам города через Интернет. Литература 1. Глушаков С.В., Ломотьков Д.В. Базы данных: Учебный курс. – К.: Абрис, 2000. -504с. 2. Джейсон Мейнджер. Java: основы программирования :Пер ...
0 комментариев