Когда следует использовать объекты в OCaml?
Обычно программа OCaml может быть написана с объектами или без них. Когда лучше всего использовать объекты и когда их следует избегать?
1 ответ
Как правило, не используйте предметы. Дополнительная сложность, которую они вносят, не так уж часто стоит. Я думаю, что это правило применимо и к другим языкам, но это другая история. По крайней мере, с OCaml можно объективно (без каламбура) сказать, что обычная практика - не использовать объект, кроме как в редких случаях.
Объект предоставляет пакет из:
- "Стандартный" стиль для переноса и использования записей функций, возможно с полиморфными типами
- Услуги для открытой рекурсии через
self
(наследование реализации) - Структурный, расширяемый тип продукта с полиморфизмом строк (для открытых типов объектов) и подтипами (для закрытых типов объектов)
Вы можете использовать любой из них вместе или по отдельности.
По моему опыту, один пункт (1) не особенно полезен для использования объектов: вы можете просто использовать записи функций, и это так же ясно.
Использует случаи открытого рекурсивного / наследования
Пункт (2), напротив, является хорошим обоснованием для использования объектно-ориентированного стиля; таким образом он используется Camlp4, например: Camlp4 определяет классы, которые сгибаются по AST, ничего не делая, и вы можете наследовать этот объект обхода, чтобы реализовать желаемое поведение только на тех синтаксических конструкциях, которые вы хотите (и отложить скучный обход твоя мама класс).
Например, можно расширить объект Camlp4Ast.map, который определяет простую функцию map в представлении Camlp4 абстрактных синтаксических деревьев OCaml, просто рекурсивно сопоставляя каждую конструкцию с самим собой. Если вы хотите, скажем, отобразить все (fun x -> e1) e2
выражения для let x = e2 in e1
, вы наследуете от этого объекта и переопределяете expr
метод, обрабатывающий только тот случай, который вы хотите (левая часть - функция), делегирующий другой в унаследованное поведение. Это даст вам объект, который знает, как применить это преобразование ко всей программе, рекурсивно, без необходимости писать какой-либо шаблонный код; и вы можете расширить эту трансформацию дополнительным поведением, если хотите.
Веселье с типами объектов
Точка (3) также является оправданием для использования объектов в качестве "расширяемых записей" или "массивов уровня типа"; некоторые библиотеки используют типы объектов, но не объекты во время выполнения: они используют типы объектов в качестве фантомных типов для переноса информации, получая выгоду от более богатых операций на уровне типов, которые вы можете выполнять над объектами. Кроме того, структурная типизация позволяет различным авторам иметь совместимые типы без сильных зависимостей от общего компонента, определяющего (номинальные) типы, которые они разделяют; объекты были использованы для стандартизации компонентов ввода / вывода, например.
Весьма простой, очень простой вариант использования этого - идиоматический способ представления типов, которые имеют много параметров. Вместо того чтобы писать:
type ('name, 'addr, 'job, 'id) person = ....
val me : (string, string, Job.t, Big_int.big_int) person
вы можете использовать типы объектов в качестве структурных "записей уровня типа" для записи:
type 'a person = .... constraint 'a = < name:'n; addr:'a; job:'j; id:'i >
val me : < name:string; addr:string; job:Job.t; id:Big_int.big_int > person
Для более расширенного использования типов объектов в качестве фантомных типов вы можете взглянуть на библиотеку ShCaml ( doc) (где она используется для представления, с какими командами оболочки совместим ввод строки) Алеком Хеллером и Джесси Товом, или моим собственная библиотека Macaque ( doc и api doc), которая использует типы объектов для представления значений SQL (включая информацию об обнуляемости) и типов строк таблицы.
Полиморфные варианты (еще одна продвинутая особенность системы типов OCaml; в предложении отношение между объектами и записями такое же, как отношение между полиморфными вариантами и типами алгебраической суммы). Также использовались в качестве фантомных типов, например, в этом простом примере Ричардом Джонсом, или для проверки достоверности документов HTML в рамках Ocsigen.
Имейте в виду, однако, что эти продвинутые хакерские атаки требуют значительных затрат; перед их использованием необходимо тщательно сбалансировать их с дополнительной выразительностью и статической безопасностью, которые они приносят.
Подводя итоги
в качестве базового предположения вы в безопасности, не используя объекты вообще; Вы должны вводить их в свой дизайн, только если чувствуете, что упускаете что-то, а не по умолчанию.
объекты удобны для открытой рекурсии / наследования: уточнение поведения, которое уже определено в стандартных / скучных случаях
Структурная типизация иногда полезна, когда вы хотите обосновать значения независимо, предоставляя набор функций / возможностей