Глава 12 Расширения языка
26 Кортежи с метками
(Добавлено в OCaml 5.4)
|
Начиная с OCaml 5.4, элементам кортежа можно при желании присваивать метки. Эта возможность концептуально противоположна именованным аргументам функций: она позволяет давать понятные имена создаваемым значениям, тогда как именованные аргументы функций позволяют давать понятные имена параметрам.
Вот пример, иллюстрирующий задачу: вычислить два значения по списку и не перепутать их:
let sum_and_product ints =
let init = ~sum:0, ~product:1 in
List.fold_left (fun (~sum, ~product) elem ->
let sum = elem + sum in
let product = elem * product in
~sum, ~product) init ints
val sum_and_product : int list -> sum:int * product:int = В этом примере показано использование кортежей с метками в типах и шаблонах. Метки можно опускать, как и у элементов записей или аргументов функций.
В типах метки элементов кортежа записываются так же, как метки аргументов функций. Например, аргумент функции fold_left из предыдущего примера имеет тип:
(sum:int * product:int) -> int -> sum:int * product:int
Кортежи с метками могут быть полезны, когда нужно использовать имена, чтобы пояснить или различить элементы кортежа, но создание новой записи кажется излишне громоздким.
Некоторым элементам кортежа можно присвоить метки, а другим — нет. Это бывает полезно, когда элементы одного типа нужно различать, а остальные — нет. Например:
type min_max_avg = min:int * max:int * float
Изменение порядка и неполные шаблоны
Как и в случае с записями, порядок элементов в шаблонах кортежей с метками можно менять, а шаблоны могут быть неполными. Компилятор поддерживает изменение порядка и неполное сопоставление только тогда, когда тип шаблона известен из контекста.
Например, можно написать:
let lt = ~x:0, ~y:42 let twice_y = let ~y, .. = lt in y * 2 val lt : x:int * y:int = (~x:0, ~y:42) val twice_y : int = 84
Если тип неизвестен (в том же смысле, в каком тип должен быть известен для устранения неоднозначности между конструкторами), компилятор отклонит неполный шаблон. Например, эту программу
let get_y t = let ~y, .. = t in y Error: Could not determine the type of this partial tuple pattern.
Эту проблему можно решить, добавив аннотацию типа к параметру функции.
В кортеже нельзя повторять метки. Однако можно считать, что все элементы без меток имеют одну и ту же уникальную метку. При сопоставлении с таким кортежем первый элемент без метки в шаблоне связывается с первым элементом без метки в значении, второй — со вторым и так далее. Поэтому можно также использовать неполный шаблон для кортежа без меток, чтобы получить первые несколько элементов.
Ограничения
Скобки необходимы, чтобы различать типы функций с именованными аргументами и типы функций с аргументами-кортежами, содержащими элементы с метками, если первый элемент кортежа имеет метку.
В отличие от записей, в выражениях с кортежами с метками нельзя менять порядок элементов, даже если тип известен. Это похоже на то, что определение функции с именованными аргументами должно связывать аргументы в том же порядке, что и в типе.
Для кортежей с метками не поддерживается проекция (извлечение элемента кортежа по метке).
Связь с гибкими записями
Кортежи с метками концептуально похожи на гибкие записи в SML. Основное различие в том, что записи SML канонически упорядочены по именам меток, а кортежи с метками — нет. Например, x:int * y:bool и y:bool * x:int в OCaml — разные типы, соответствующие разному порядку полей в блоке времени выполнения. В SML соответствующие типы записей считаются равными, а поля в блоке времени выполнения всегда упорядочены так, что поле x идёт первым.
© 1995-2026 INRIA.
https://ocaml.org/manual/5.5/labeledtuples.html