Ремонт принтеров, сканнеров, факсов и остальной офисной техники


назад Оглавление вперед




[17]

задает независимую среду в том смысле, что объявления, появившиеся внутри инкапсулированного объявления, никак не влияют на другие объявления, выполненные на верхнем уровне. Так, например, после приведенного выше примера ни t, ни f недоступны на верхнем уровне.

Однако к идентификаторам, объявленным внутри структуры, может быть получен доступ с помощью составных (qualified) имен. Составное имя состоит из пути доступа к структуре, точки и самого идентификатора. В настоящий момент путь доступа к структуре будет состоять просто из идентификатора структуры; позже нам придется обобщить понятие пути до последовательности идентификаторов структур. Мы можем использовать компоненты структуры S с помощью составных имен следующим образом:

Type checking error in: х Unbound value identifier: x

>3 : int

-S.f(S.x);

>6 : int

-S.x : S.t;

>3 : S.t

Выражение S.x является составным именем, которое ссылается на значение, к которому привязан идентификатор х в структуре S. Значение выражения S.x, как вы и можете предположить, есть 3. Аналогично, S.f обозначает функцию f, объявленную в структуре S (функцию вычисления факториала). Когда она применяется к S.x (т.е. к 3), результатом будет 6. Использование идентификаторов, объявленных в S, не ограничивается значениями: последний пример показывает возможность использования идентификатора типа S.t, объявленного в S как int.

Если в какой-то части программы упоминаются несколько компонент одной и той же структуры, выписывание составных имен превращается в утомительное занятие. Чтобы облегчить жизнь в таких ситуациях, ML предоставляет возможность "открыть" структуру с тем, чтобы к определенным внутри нее идентификаторам стал возможен непосредственный доступ.

-let open S in f(x) end;

>6 : int

-open S;

>val x = 3 : int

val f = fn : int -> int type t = int


В первом примере мы локально открываем структуру S внутри выражения let, что позволяет писать f (х) вместо громоздкого S.f(S.x). Во

втором примере мы открываем структуру S на верхнем уровне, и тем самым добавляем к среде верхнего уровня новые привязки идентификаторов - как это и видно из выдачи ML.

Часто бывает полезно рассматривать структуры как значения некоторого особого рода, поскольку, во-первых, это соответствует представлению о среде как о некотором объекте, а, во-вторых, имеется некоторый набор операций над структурами. В ядре языка каждое значение имеет тип; аналогично, структуры также имеют типы: это сигнатуры. Сигнатуры характеризуют структуры во многом подобно тому, как обычные типы характеризуют обычные значения, описывая способы, которыми значение может быть использовано в процессе вычислений. Хотя, строго говоря, сигнатуры не являются типами, но, тем не менее, аналогия между сигнатурами и типами должна помочь вам понять, для чего нужны сигнатуры.

Если мы рассмотрим выдачу ML в приведенных выше примерах, то увидим некоторые различия между выдачей в случае обычной привязки к значению и в случае привязки к структуре. А именно, при обычной привязке к значению, ML в ответ печатает и значение, и его тип. В случае же привязки к структуре печатается только значение. Давайте рассмотрим, что бы произошло, если бы ML твердо придерживался принципов работы с обычными значениями и в случае структурных значений:

- structure S = struct

val х = 2+2;

val b = (x=4) end;

> structure S = struct

val x = 4

val b = true end

val x : int

val b : bool end

В этом причудливом примере информация о типах переменных появляется внутри сигнатуры, в то время как значения появляются внутри структуры. Это соответствует нашему интуитивному пониманию сигнатуры как характеристики значения (именно, структуры). Ясно, что если бы результат привязки к таким "толстым" объектам как структуры


печатался в том же виде, как и результат привязки к обычным значениям, результат печати получался бы слишком громоздким, и поэтому ML-системы печатают результат привязки к структуре как некоторую "смесь" из структуры и ее сигнатуры.

Выражение, заключенное в скобки sig и end в приведенном выше примере, называется сигнатурой; его тело называется спецификацией. Спецификация во многом подобна объявлению, с тем отличием, что она только описывает идентификатор, связывая с ним тип, а не придает идентификатору значение (из которого в случае обычного объявления выводится тип). Пока что мы рассмотрели только val-спецификации; позднее мы рассмотрим и другие. В приведенном выше примере указывается, что х имеет тип int, a b имеет тип bool.

Сигнатуры не только выводятся ML-компилятором. Они играют важную роль в использовании модульной системы, в частности, при объявлении функторов, и поэтому они часто пишутся пользователем. Идентификатор может быть привязан к сигнатуре путем привязки к сигнатуре

-подобно привязке к типу. Привязка к сигнатуре обозначается ключевым словом signature, и может появляться только на верхнем уровне.

-signature SIG =

val x : int

val b : bool end;

> signature SIG = sig

val x : int

val b : bool end

Поскольку информация выдаваемая ML в ответ на объявление сигнатуры не содержит ничего интересного, в последующих примерах она будет опускаться.

Основная польза сигнатур заключается в том, что структуры могут сопоставляться с сигнатурами. Структура называется сопоставимой с сигнатурой, если, грубо говоря, структура соответствует спецификациям сигнатуры. Поскольку спецификации подобны типам, идея сопоставления с сигнатурой близка проверке соответствия типов в ядре языка, хотя некоторые детали здесь довольно сложны. Один из способов использования сигнатуры состоит в указании ее после имени структуры при привязке идентификатора к структуре (что очень похоже на указание типа при привязке идентификатора к обычному значению) с целью обеспечения дополнительной проверки в период компиляции:

- structure S : SIG =



[стр.Начало] [стр.1] [стр.2] [стр.3] [стр.4] [стр.5] [стр.6] [стр.7] [стр.8] [стр.9] [стр.10] [стр.11] [стр.12] [стр.13] [стр.14] [стр.15] [стр.16] [стр.17] [стр.18] [стр.19] [стр.20] [стр.21] [стр.22] [стр.23] [стр.24] [стр.25] [стр.26] [стр.27] [стр.28] [стр.29] [стр.30] [стр.31] [стр.32]