Ремонт принтеров, сканнеров, факсов и остальной офисной техники


назад Оглавление вперед




[6]

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

-val {used=u,...} = г;

>val u = true : bool

Существенным ограничением при использовании универсального образца для записей является следующее: полный тип записи должен определяться на этапе компиляции (т.е. полный список имен полей записи и их типов должен определяться по контексту, в который входит образец).

Поскольку выделение одного поля из записи является широко распространенной операцией, для нее предусмотрено специальное обозначение: поле name записи г может быть обозначено как #name г. На самом деле #name является не более чем сокращенным обозначением для функции fix {name=n, . . .} => п, выделяющей поле name из записи. Поэтому, в частности, тип записи должен определяться из контекста, в котором эта функция используется. Например, fix х => #ixame х будет ошибкой, поскольку тип записи х не определяется однозначно контекстом. Поскольку упорядоченные энки являются частным случаем записи (именами полей у них являются целые числа от 1 до и), г-тая компонента упорядоченной энки может быть выделена с помощью функции #i.

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

-val х = (("fоо",true), 17);

>val x = (("f oo" ,true), 17) : (string*bool)*int

-val ((11,lr), r) = x;

>val 11 = "foo" : string val lr = true : bool val r = 17 : int

Иногда бывает удобно ввести "промежуточные" переменные в образце. Например, нам может понадобиться привязать к паре (11, гг) идентификатор 1. Это выполняется с помощью многоуровневых образцов. Многоуровневый образец получается путем приписывания образца к переменной внутри другого образца, как в следующем примере:

-val х = (("foo", true), 17);

>val x = (("foo", true), 17): (string*bool)*int

-val (1 as (11,lr), r) = x;

>val 1 = ("foo", true): string*bool val 11 = "foo": string

val lr = true : bool val r = 17 : int


Здесь сопоставление с образцом выполняется обычным способом: 1 и г привязываются к значениям левой и правой компонент х, но дополнительно производится сопоставление привязанного к 1 значения с образцом (11,1г). Результат выводится как обычно.

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

Упражнение 2.4.2 Постройте образец, который привязывал бы переменную х к значению 0 при сопоставлении со следующим выражением (например, если дано выражение (true, "hello" ,0), образцом должно быть ( , ,х):

1.{а=1, b=0, c=true>

2.[~2, ~1, 0, 1, 2]

3.[(1,2), (0,1)]

2.5 Определения функций

Мы уже использовали предопределенные функции, такие, как арифметические операции и операции сравнения. В этом разделе мы рассмотрим привязки к функциональным значениям, посредством которых в ML определяются новые функции.

Начнем с нескольких общих замечаний, касающихся понятия функции в ML. Функции используются путем применения их к аргументам (мы будем также использовать термин аппликация). Синтаксически это записывается как два выражения одно за другим (значением первого выражения должна являться функция, а значением второго - ее аргумент) - как, например, size "abc" для вызова функции size с аргументом "abc". Все функции являются функциями одного аргумента; при необходимости использовать функции (содержательно) нескольких аргументов, n аргументов функции "упаковываются" в один - упорядоченную энку. Так, например, если функция append должна получать два аргумента-списка и возвращать результат-список, применение ее будет иметь вид append(ll ,12): формально функция применяется к одному аргументу, который является упорядоченной парой (11,12). Для некоторых функций от двух аргументов (обычно, встроенных) используется специальный синтаксис - так называемая инфиксная запись, в которой знак функции записывается между двумя ее аргументами. Например, запись в\ + в2 в действительности означает "применить функцию + к упорядоченной паре (ei, в2)". Можно использовать инфиксную запись


и для функций, определяемых пользователем, однако мы не будем здесь на этом останавливаться.

Аппликация в ML может иметь более сложную форму, чем в других языках программирования. Причиной этого является следующее: в большинстве языков программирования функция может обозначаться только идентификатором, и поэтому вызов функции всегда имеет вид f(ei, . . . ,en), где f - идентификатор. В ML нет такого ограничения: функция является обычным значением, и может быть получена в результате вычисления выражения. Поэтому в общем случае аппликация в ML имеет вид ее. Вычисление такого выражения выполняется следующим образом: сначала вычисляется выражение в, в результате чего получается некоторая функция /; затем вычисляется выражение в, в результате чего получается некоторое значение у; после этого функция / применяется к значению v. В простейшем случае, когда выражение в

ся крайне простой операцией: нужно просто взять значение, к которому привязан идентификатор (оно должно быть функцией). Но в общем слу-

те внимание на то, что правила вычисления аппликации предполагают передачу аргумента по значению, поскольку аргумент вычисляется до применения функции.

число)? Чтобы ответить на этот вопрос, конечно, следует посмотреть, в

в ML имеет тип. Функциональные типы являются составными типами, членами которых являются функции. Функциональные типы записываются как а -> т (произносится "а в т"), где а и т - типы. Выражение такого типа имеет в качестве значения функцию, которая может быть

(к сожалению, в общем случае невозможно определить, завершается ли

а тв ат

Например:

>size = fix : string -> int

>not = fn : bool -> bool

-not 3;

Type clash in: not 3



[стр.Начало] [стр.1] [стр.2] [стр.3] [стр.4] [стр.5] [стр.6] [стр.7] [стр.8] [стр.9] [стр.10] [стр.11] [стр.12] [стр.13] [стр.14] [стр.15] [стр.16] [стр.17] [стр.18] [стр.19] [стр.20] [стр.21] [стр.22] [стр.23] [стр.24] [стр.25] [стр.26] [стр.27] [стр.28] [стр.29] [стр.30] [стр.31] [стр.32]