Селекторные операции
Для каждого типа данных (в частности, для любого скалярного типа) в Манифесте требуется, помимо прочего, определение операции, назначение которой состоит просто в "выборке" конкретного значения данного типа. Такие селекторные операции являются обобщением знакомого понятия литерала. (Литерал - это специальный случай вызова селектора, но не все вызовы селектора являются литералами.) Например, рассмотрим следующий фрагмент кода:
VAR X RATIONAL INIT ( +4.0 ) ; VAR Y RATIONAL INIT ( -3.0 ) ; VAR P POINT ;
P : = POINT ( X, Y ) ;
(Пример выражен на языке Tutorial D; напомним, что три месяца тому назад я говорил, что Tutorial D - это язык, определенный главным образом как средство для иллюстрации и обсуждения особенностей Манифеста. Я должен также пояснить, что везде в Манифесте мы используем более точный термин RETIONAL вместо традиционного REAL; в конце концов, числа с плавающей точкой по определению являются рациональными числами, а не действительными числами общего вида.)
Действие приведенного фрагмента кода состоит в присвоении переменной P конкретного значения POINT -- а именно, точки с Декартовыми координатами (4.0, -3.0). Выражение в правой части операции присваивания в точности представляет собой вызов селектора типа POINT; эффект вызова в точности состоит в выборе точки с указанными Декартовыми координатами. (Замечание: Если бы я написал просто POINT (4.0, -3.0) вместо POINT (X, Y), то использовал бы вызов селектора, представляющий в действительности литерал. Кроме того, для читателей, знакомых с объектными системами, я должен подчеркнуть тот факт, что в нашей модели переменная P теперь в действительности содержит точку как таковую, а не "ссылку на" точку или "объектный ID" точки. В нашей модели явно отвергаются объектные ID.)
Следовательно, заметим, что параметры данного селектора S составляют -- обязательным образом -- возможное представление PR объектов соответствующего типа T. В приведенном примере Декартовы координаты X и Y составляют возможное представление точек.
В действительности в объектных системах имеются некоторые аналоги наших селекторных операций (более обычным объектным термином является функции- конструкторы), и поэтому пользователи таких систем необходимым образом знакомы с некоторыми возможными представлениями. Однако в объектных системах, вообще говоря, не требуется, чтобы эти возможные представления раскрывались для произвольных целей. Например, пользователи могут знать на основе формата соответствующей функции-конструктора, что для точек существует возможное представление на основе Декартовых координат, но если система не обеспечивает операций для "взятия" координат X и Y для любой заданной точки, эти пользователи не смогут выполнять все разновидности простых операций. Развивая приведенный фрагмент кода, если не существует операция "get Y", то пользователь не сможет узнать, какова координата Y точки P, даже если он или она знают, что значение этой координаты есть -3.0! Другими словами, кажется, что объектная ориентация допускает не слишком разумную политику разработки.
В свете приведенных наблюдений мы решили в своем Манифесте настаивать на некоторой подходящей дисциплине. Более конкретно, мы настаиваем на следующем:
Вот пример (опять Tutorial D):
TYPE POINT POSSREP POINT ( X RATIONAL, Y RATIONAL ) POSSREP POLAR ( X RATIONAL, Y RATIONAL ) ;
Этот оператор определяет уже использовавшийся в предыдущих примерах тип POINT. У типа POINT имеются два возможных представления, называемых POINT (Декартовы координаты) и POLAR (полярные координаты) соответственного, и два соответствующих селектора с такими же именами. (В Tutorial D мы используем еще одно соглашение, в соответствии с которым возможное представление без собственного явно заданного имени по умолчанию наследует имя соответствующего типа; таким образом, в первой из двух спецификаций POSSREP в приведенном примере явное имя POINT можно было бы опустить.)
Конечно, в Манифесте требуется, чтобы типы кортежей и отношений также обладали селекторами. Однако для простоты здесь я буду концентрироваться на скалярных типах.