Синонимы в сопоставлении с образцом n Ключевое слово as n match [1;2;3] with e1::( (e2::tail2) as tail1) -> … n Позволяет избежать лишнего сопоставления с образцом, как, например, в n match [1;2;3] with e1::tail1 -> … match tail1 with e2::tail2 -> …
Условия в сопоставлении с образцом n Ключевое слово when n let rec remove_duplicates = function (* работает на отсортированном списке *) | [] -> [] | [x] -> [x] | e1::e2::tail when e1 == e2 -> e1::(remove_duplicates tail) | e::tail -> e::(remove_duplicates tail) n В OCAML нельзя писать | e::e::tail -> …
Интервалы в сопоставлении с образцом n | A..Z -> заглавная буква
Синтаксис языка OCAML n Кортеж (tuple) n Кортеж есть упорядоченный набор объектов языка возможно различного типа u (1, 2, 3.14, abc, [4; 5], (6, 7), 8) n Сравнение кортежа и списка u Тип объектов n В кортеже: произвольный n В списке: один и тот же u Размер n Для кортежа: фиксированный n Для списка: переменный
Кортеж и сопоставление с образцом n В сопоставлении с образцом кортеж указывается «полностью»: u match (1, a, 2, b, 3) with (x, _, y, _, 3) -> printf got x = %d, y = %d\n x y n Теоретически и практически кортеж аналогичен «записям» и «структурам» ИП. n Удобнее тем, что не нужно описывать типы компонент и давать им имена n Кортеж – «запись» ad hoc
Кортежи и функции n В OCAML все функции – каррированные: u fun x y -> x + y тождественно равно n function x -> function y -> x + y n Кортеж позволяет задать «традиционную» (некаррированную) функцию нескольких аргументов: u function (x, y) -> x + y n На практике это имеет смысл только в тех случаях, когда кортеж аргументов представляет собой осмысленное целое. u Например, координаты точки на поверхности: u function (x0, y0) (x1, y1) -> abs(x1-x0) + abs(y1-y0)
Кортеж и сопоставление с образцом, 2 n let rec addlists list1 list2 = match list1, list2 with | [], list2 -> list2 | list1, [] -> list1 | h1::list1, h2::list2 -> (h1+h2)::(addlists list1 list2)
Записи (records) n Запись – это кортеж, в котором компоненты идентифицируются именем, а не позицией в кортеже. n Запись невозможно задать ad hoc. n Требуется описание типа. u type имя_типа = { имя_поля1: тип_поля1; …; имя_поляN: тип_поляN } n Базовые типы объектов: int, string, float, char, bool n Пример: u type shopping_cart = {item_id: string; quantity: int} n Сравнимо с С: u struct shopping_cart { char *item_id; int quantity; }
Записи и сопоставление с образцом n «Конструктор» записи: u {item_id: battAA; quantity: 4} n Сопоставление с образцом: u let check_max_quantity cart = match cart with { item_id = id; quantity = q} -> q < 10 u let getQuantity { quantity = q } -> q n Имя типа не указывается ни в конструкторе, ни при сопоставлении с образцом n Поэтому имена полей должны быть уникальны в пределах модуля n {name: string, salary: float} и {name: string, engine_power: float }
Вариантные типы n type street_light = Red | Yellow | Green n type length = In of float | Cm of float n let length_sum 1l, l2 -> | In i1, In i2 -> In (i1 +. i2) | Cm c1, Cm c2 -> Cm (c1 +. c2) | In i1, Cm c2 -> Cm (i1 / c2) | Cm c1, In i2 -> Cm (c1 +. i2 /. 2.54) n Типы в of ___ не обязаны быть одинаковыми. n Аналог union и enum C++
Кортежи и описания типов n type silly_dist_type = Meters of float | FtIn of (int * float) n let my_meters = Meters 5.73;; n let my_fts = FtIn (18, 9.59);; n type time = Time of (int * int * float);; (* ч. мин. сек. *)
Параметрический полиморфизм n type t mytree = Leaf of t | Branch of (t mytree * t mytree);; n «Конструктор» записи: u {item_id: battAA; quantity: 4} n Сопоставление с образцом: u let check_max_quantity cart = match cart with { item_id = id; quantity = q} -> q < 10 u let getQuantity { quantity = q } -> q n Имя типа не указывается ни в конструкторе, ни при сопоставлении с образцом n Поэтому имена полей должны быть уникальны в пределах модуля n {name: string, salary: float} и {name: string, engine_power: float }
Типы функциональных значений let sum x y = x + y;; sum : int -> int -> int let rec length = function | [] -> 0 | _::list -> 1 + length list;; length : 'a list -> int