Standart ML. Урок 9. Образцы

Standart ML   25 октября 2013  Автор статьи:  
Задача образцов

Нужно переменным left, centre, rigth одновременно присвоить значения 21, «желудь», 15 с помощью образцов.

Допустим есть упорядоченная энка:

- val x = (21, "желудь", 15);

Заметим, что x имеет тип int * string * int. Тогда x является тройкой, левая и правая компоненты которой являются целым значением, а центральная — строкой.

> val x = (21, "желудь", 15) : int * string * int

Можем получить значения левой, центральной и правой компонент, используя следующую обобщенную форму привязки к значению:


- val (left, centre, rigth) = x;
> val left = 21 : int
val centre = "желудь" : string
val rigth = 15 : int

Задача решена.

obrazez

[note]Выделение частей составных значений выполняется с помощью сопоставления с образцом (выражение, возможно, включающее переменные).
[/note]

[important]Переменные в образце являются переменными, которые должны быть привязаны к значениям в процессе сопоставления с образцом.[/important]

Сопоставление с образцом

Сопоставление с образцом состоит в

  • параллельном разложении на составные части значения x и образца (left, centre, rigth);
  • сопоставлении компонент значения с соответствующими им частями образца (left с 21, centre с «желудь», rigth с 15).

Идентификаторы left, centre, rigth привязываются к значению x. Таким образом, если сказать, что а = 100500, выдастся false, т.к. а = 20.

— a = 100500;
> val it = false : bool

identFalse

Если образец содержит константу (20), то она должна совпадать с соответствующей частью значения, с которым выполняется сопоставление (20, 15), иначе возникнет ошибка сопоставления.

bindSopost

Внутренняя структура сопоставляемых образцов должна быть одинаковой:

structureByObrazez

Помните о типах! Сопоставление с образцом (a, b, c, d) может быть выполнено для значений любого из введенных ранее типов. Например, список целочисленных значений int list:

listObrazez

Джокер

Имена переменных, которые не нужны для использования в дальнейшем, можно не указывать. Вместо них следует писать знак подчеркивания _ («джокер»). Джокер, в свою очередь, может быть сопоставлен с любым значением без привязки к нему идентификатора.


- val m = ("опушка", 6.961, 2);
> val m = ("опушка", 6.961, 2) : string * real * int
- val (what, _, amount) = m;
> val what = "опушка" : string
val amount = 2 : int

djoker

Сопоставление с образцом может быть применено для записей:

- val z = {what = "kedr", how = 6};
> val z = {how = 6, what = "kedr"} : {how : int, what : string}
- val {what = wh, how = h} = z;
> val wh = "kedr" : string
val h = 6 : int

zamenaObrazez

Сопоставление с образцом может быть применено для записей частично:

- val z = {d = 7, r = 2.1, a = 8};
> val z = {a = 8, d = 7, r = 2.1} : {a : int, d : int, r : real}
- val {r = radius, ...} = z;
> val radius = 2.1 : real

chastichnoeSopost

Образцы могут вкладываться друг в друга:

- val ob = (("yes", 2), true);
> val ob = (("yes", 2), true) : (string * int) * bool
- val ((a, b), d) = ob;
> val a = "yes" : string
val b = 2 : int
val d = true : bool

vklObr

Список произвольной длины

Чтобы разложить список произвольной длины на компоненты, воспользуемся следующей конструкцией
(one :: ost = sp):

- val sp = [2.12, 14.2, 81.9, 14.812];
> val sp = [2.12, 14.2, 81.9, 14.812] : real list
- val one :: ost = sp;
> val one = 2.12 : real
val ost = [14.2, 81.9, 14.812] : real list

Заметим, one привязывается к значению первой компоненты (голове списка), а ost к списку без головы (хвосту). Тип переменной one — real, ost — real list.

spOst

Если нужна только голова списка, воспользуемся джокером:

- val one :: _ = sp;
> val one = 2.12 : real

Промежуточные переменные

Допустим, к паре (two, three) нужно привязать идентификатор one. Это возможно с помощью многоуровневых образцов.
Многоуровневый образец получается путем приписывания образца к переменной внутри другого образца
(one as (two, three):


- val sp = (("year", 2013), 2);
> val sp = (("year", 2013), 2) : (string * int) * int
- val (one as (two, three), four) = sp;
> val one = ("year", 2013) : string * int
val two = "year" : string
val three = 2013 : int
val four = 2 : int

mnogourObrazez

[important]Любая переменная может входить в образец только один раз. Нельзя задать образец (x, x), который был бы сопоставим только с симметричными парами.
[/important]

Конструкция case

Конструкция case производит сопоставление с образцом, выдавая результат в зависимости от результата сопоставления.

Общий формат конструкции case:


- case (x, y)
of (значение x, значение y) => "что вывести"
| (значение x, значение y) => "что вывести"
| _ => "что вывести";

Вертикальная черта | означает или, а знак подчеркивания _ — любые другие значения.

Рассмотрим пример, в котором по дате (day, month) выдается название праздника:


- val day = 6 and month = 5;
> val day = 6 : int
val month = 5 : int
- case (day, month)
of (6, 5) => "мой День Рождения"
| (1, 4) => "День Смеха"
| (1, 9) => "День Знаний"
| _ => "Не описано";
> val it = "мой День Рождения" : string

case

В следующем уроке познакомимся с функциями, не расслабляйтесь!

Научиться программировать

  • на Delphi

  • на Java

  • на C++