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


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




[15]

-exception Ехс; > exception Ехс

-(let exception Ехс in raise Ехс end) handle Ехс => 0; Failure: Ехс

Несмотря на то, что идентификатор Ехс объявлен на внешнем уровне, внешний обработчик не может распознать исключение, возникшее внутри конструкции let, поскольку область видимости этого исключения, лежит внутри конструкции let. (Однако обработчик с образцом " " смог бы обработать это исключение).

Упражнение 2.8.1 Объясните, что неправильного в следующих двух программах:

1.exception Ехп of bool; fun f х =

let exception Ехп of int

in if x> 100 then raise Ехп x else x+1 end; f(200) handle Exn true => 500 I Exn false => 1000;

2.fun f x =

let exception Exn in

if p x then a x else if q x

then f(b x) handle Exn => с x

else raise Exn end; f v;

Упражнение 2.8.2 Напишите программу, размещающую n ферзей на шахматной доске размером n* n так, что ни одна из фигур не нападает на другую.

Упражнение 2.8.3 Модифицируйте предыдущую программу так, чтобы она возвращала все решения задачи.

2.9 Императивные возможности языка

ML разрешает использовать ссылки и присваивания. Ссылки являются указателями в кучу, для которых выполняется проверка согласования типов. Присваивания позволяют изменять значение, на которое указывает ссылка. Тип г ref является типом ссылок на значения типа г17. Функция ref типа а -> a ref выделяет в куче место для аргумента,

17В настоящее время т может быть только мономорфным типом: однако предполагается в будущем включить в язык один из рассматриваемых ныне способов работы с полиморфными ссылками.


копирует туда аргумент и возвращает в качестве результата ссылку на это место. Функция ! типа a ref -> а вырабатывает то значение, на которое указывает ссылка. Функция := типа a ref * а -> unit выполняет операцию присваивания.

- val х = ref 0;

> val х = ref(0): int ref

> 3 : int

Все ссылочные типы допускают проверку на равенство. Объекты типа т ref являются адресами в куче, и два таких объекта равны тогда и только тогда, когда они совпадают. Заметьте, что хотя равные ссылки заведомо указывают на одно и то же значение, обратное не всегда верно: на одно и то же значение могут указывать и несколько неравных ссылок!

= ref 0;

= ref 0 :

= ref 0;

= ref 0 :

Это соответствует ситуации в языках типа Pascalя, где можно иметь две различные переменные, содержащие одинаковые значения (в данный момент). Для тех, кто знаком с LISPom, заметим, что равенство ссылок в ML соответствует функции eq, а не equal.

Вместе со ссылками в языке появляются обычные для императивного языка конструкции: композиция последовательных утверждений и итеративное выполнение. В ML утверждения представляются выражениями типа unit (тип их выражает идею того, что эти выражения вычисляются ради их побочного эффекта, а не ради значения выражения). С помощью инфиксной операции " ;" осуществляется последовательное выполнение утверждений, а конструкция while e do ё обеспечивает итеративное выполнение.

Упражнение 2.9.1 Следующий абстрактный тип данных может быть использован для создания бесконечного потока значений:

abstype a stream = stream of unit -> (a * a stream)

- !x; > 0 :

int ; 3; unit;


with fun next(stream f) = f() val mkstream = stream

Если дан некоторый поток S, то next S возвращает первое значение из S и поток, состоящий из остальных значений. Это иллюстрируется следующим примером:

-fun natural n = mkstream(fn () => (n, natural(n+1)));

>val natural = fn : int -> int stream

-val s = natural 0;

>val s = - : int stream

-val (first, rest) = next s;

>val first = 0 : int

val rest = - : int stream

-val (next, ) = next rest;

>val next = 1 : int

Напишите функцию, которая возвращает бесконечный список простых чисел в виде потока.

Упражнение 2.9.2 Приведенная выше реализация потока как абстрактного типа данных может оказаться крайне неэффективной, если одни и те же элементы потока используются многократно. Это происходит потому, что функция next вычисляет очередной элемент потока всякий раз, когда она вызывается. Повторное вычисление будет бесполезной тратой времени для таких потоков, как, например, простые числа, где возвращаемое значение будет всегда одним и тем же. Измените объявление типа Stream с использование ссылок так, чтобы устранить эту неэффективность.

Упражнение 2.9.3 Измените объявление типа stream так, чтобы он допускал как конечные, так и бесконечные потоки, используя предикат endof stream для определения конца потока.



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