Алексей Махоткин

домашняя страница

Критика Standard ML — изменяемые объекты

Andrew W. Appel, «Критика Standard ML», оглавление

Несмотря на то, что у значений есть множество полезных свойств, не следует отбрасывать идею изменяемых объектов. Только экстремист скажет, что ячейки с обновлением слишком сложно использовать и понимать. Экстремисты, впрочем, вполне могут оказаться и правы: совершенно ясно, что любой алгоритм с объектами можно симулировать с помощью алгоритма со значениями, а недавние исследования показали, что такие алгоритмы легче читать и понимать. Однако, миллионы программистов хорошо понимают, что такое присваивание и обновляемые структуры данных, и успешно пишут свои программы. Конечно, точно тот же довод можно привести в пользу возврата к оператору GOTO и 64-килобайтному адресному пространству. Однако же, программирование с обновлениями — проверенная технология, а программирование совсем без обновлений — все еще «исследования».

Итак, другие языки сочетают функциональный стиль с возможностью обновлений: например, Scheme. Остается один вопрос: как совместить два этих стиля, не теряя преимуществ использования неизменных значений? Если разрешить обновления, то «глупые» вопросы из предыдущей главы внезапно обретают чрезвычайно запутанные ответы.

ML решает эту проблему, тщательно разделяя изменяемые и неизменные типы. Целое значение имеет тип int, а изменяемая ячейка, содержащая целое значение, имеет тип int ref; это два разных типа. Можно извлечь неизменное значение из int ref и привязать его к переменной типа int; можно записать какое-то другое (неизменное) значение в int ref. Только для ссылочных значений важны вопросы совместного использования и тождественности.

Ссылочные ячейки могут быть компонентами структур данных. Например, ниже показан тип tree: это тип неизменных деревьев с целыми листьями; элементы типа tree1 — это деревья, чьи листья можно изменять, но чья структура неизменна. И наоборот, листья у tree2 неизменны, а структуру дерева можно изменять (и можно даже вставлять совершенно новые листья):

datatype tree
       = LEAF of int
       | NODE of tree * tree


datatype tree1
       = LEAF of int ref
       | NODE of tree1 * tree1


datatype tree2
       = LEAF of int
       | NODE of tree2 ref * tree2 ref

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

Comments