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


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




[4]

-val s = "Abc"A"defl

>val s = "Abcdef" : string

-val pair = (x, s);

>val pair = (20, "Abcdef"): int * string

Фраза val x = 4*5 называется привязкой к значению. Чтобы выполнить привязку, ML вычисляет значение выражения справа от знака равенства и устанавливает значение переменной, указанной слева от знака равенства, равным вычисленному значению. В приведенном выше примере х привязывается к целому числу 20. После этого идентификатор х навсегда остается привязанным к этому значению; так, значение (x,s) образуется из значений х и s. Обратите внимание на то, что выдача ML теперь слегка отличается от приводившихся ранее: перед значением переменной печатается "х = ". Причиной этого является то, что сразу после того, как идентификатор объявлен, ML печатает его определение (форма определения зависит от сорта идентификатора; пока что мы видели только переменные, для которых определением является значение переменной). Напомним, что когда на верхнем уровне диалога (в ответ на запрос ввода) вводится выражение, то оно вычисляется, и затем печатается его значение вместе с типом. На самом деле здесь ML привязывает к этому значению идентификатор it, так что в дальнейших фразах верхнего уровня диалога идентификатор it может использоваться для доступа к этому значению7.

Важно отметить отличие понятия переменной в ML от понятия переменной в других языках программирования. Объявление переменной в ML более похоже на описание const в Pascale, нежели на описание var; в частности, привязка не является присваиванием. Когда некоторый идентификатор привязывается к значению, "создается" новый идентификатор - и он не имеет никакого отношения к (возможно) ранее объявленному такому же идентификатору. Более того, после того, как идентификатор привязан к значению, нет никакого способа изменить это значение: его значение всегда остается тем, к которому мы привязали его в момент объявления. Если вы незнакомы с функциональными языками программирования, это может показаться несколько странным; подождите, пока мы не рассмотрим примеры программ и не покажем, как это может использоваться. Так как ранее объявленные идентификаторы могут быть привязаны к новым значениям, необходимо уточнить, какая из привязок должна быть использована в данной точке программы. Давайте рассмотрим следующую последовательность привязок:

-val х = 17;

7Таким образом, можно считать, что ввод на верхнем уровне диалога выражения e является сокращенной формой для "val it = e". В некоторых реализациях ML этот факт явно отражен - в ответ на ввод выражения печатается "val it = значение : тип" (вместо приводимой здесь в примерах выдачи "значение : тип"). (Прим. перев.)


= true;

Вторая привязка x "заслоняет" первую (но не оказывает никакого влияния на значение переменной у). Всякий раз, когда идентификатор используется в выражении, он считается ссылающимся на текстуально ближайшую объемлющую привязку этого идентификатора. Таким образом, использование х в правой части привязки идентификатора z ссылается на вторую привязку идентификатора х, и поэтому значение z есть true, а не 17. Это правило аналогично правилам видимости в языках с блочной структурой. С помощью ключевого слова and, используемого в качестве разделителя, можно привязать к значениям сразу несколько идентификаторов:

-val х = 17;

>val х = 17 : int

-val x = true and у = x;

>val x = true : bool val у = 17 : int

Обратите внимание на то, что у получает значение 17, а не true! Несколько привязок, соединенных словом and, вычисляются параллельно - сначала вычисляются их правые части, а затем идентификаторы, указанные в левых частях, привязываются к полученным значениям.

Для того чтобы продолжить изложение, нам нужно ввести несколько определений. Мы будем говорить, что роль объявления состоит в определении идентификатора для дальнейшего использования в программе. Существуют различные возможности использования идентификатора в программе; одним из них является использование в качестве переменной. Чтобы определить идентификатор для какой-нибудь цели, необходимо использовать привязку, соответствующую этой цели. Например, чтобы определить идентификатор как переменную, следует использовать привязку к значению (которая привязывает переменную к значению и устанавливает ее тип). Другие формы привязок будут введены позже. В общем случае, роль объявления состоит в построении некоторой среды, которая определяет смысл всех объявленных идентификаторов. Например, после выполнения приведенных выше привязок к значениям среда содержит информацию о том, что значение х есть true и значение у есть 17. Вычисление выражения всегда происходит в некоторой среде; в упомянутой среде значением выражения х будет true.


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

-val х = 17; val х = true and у = х;

>val х = 17: int

>val x = true : bool val у = 17: int

Когда два объявления соединяются точкой с запятой, ML сначала вычисляет левое объявление, порождая среду E, а затем вычисляет правое объявление (в среде £), порождая среду E. Второе объявление может скрыть какие-то идентификаторы из первого объявления (как показано в примере).

Также полезно иметь локальные объявления, роль которых состоит только в том, чтобы облегчить построение других объявлений. Это может быть сделано, например, следующим способом:

val х = 10

val u = x*x + x*x val v = 2*x + (x div 5) end;

>val u = 200 : int val v = 22 : int

Привязка идентификатора x является локальной по отношению к привязкам идентификаторов и и v; х доступно в процессе привязки и и v, но не дальше. Это отражено п в результате объявления: объявлены только и и v. Имеется также возможность локализовать объявление, используемое при вычисления выражения:

val х = 10

х*х + 2*х + 1 end;

>121: int

8Точка с запятой по синтаксису необязательна: две последовательные привязки к значению считаются разделенными точкой с запятой



[стр.Начало] [стр.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]