1.4.1. ОПРЕДЕЛЕНИЯ ФУНКЦИЙ

Рефал-программа состоит из определений функций, каждое из которых имеет следующий вид:

Fname \{ Snt1; Snt2; ... Sntn; };

или

Fname { Snt1; Snt2; ... Sntn; };

где Fname - имя функции, а Snt1, Snt2, ..., Sntn - предложения.

(Тонкое различие между "\{" и "{" для нас пока не существенно и будет рассмотрено позднее.)

Каждое предложение Sntj имеет вид Pj Rj, где Pj - входной образец предложения, а Rj - хвост предложения.

Определение функции имеет следующий смысл. Предположим, что требуется вычислить вызов функции Fname вида

<Fname Re>

Тогда первым делом вычисляется результатное выражение Re. Предположим, что в результате этого получилось объектное выражение Oe. Тогда делается попытка сопоставить Oe с входными образцами P1, P2, ..., Pn, пока не найдется такой образец Pj, для которого сопоставление проходит успешно, т.е. имеется хотя бы один вариант сопоставления Oe с P. После этого из всех вариантов сопоставления Oe с P выбирается "самый первый" вариант Env, после чего в среде Env вычисляется хвост Rj. Если при этом получится некоторое объектное выражение Oe', оно и считается результатом вызова функции.

Например, определим функцию Sumsq, вычисляющую сумму квадратов двух чисел. В общепринятых обозначениях ее определение записывается в виде

Sumsq(X,Y) = X*X + Y*Y

в то время как на Рефале ее определение принимает следующий вид:

$func Sumsq sX sY = sZ;

Sumsq

{

sX sY = <"+" <"*" sX sX> <"*" sY sY>>;

};

Обратите внимание, что объявление функции должно располагаться в программе раньше как ее определения, так и первого вызова, так как информация о функции, которая содержится в ее объявлении необходима для правильной компиляции ее определения и ее вызовов.

Если объявление функции имеет вид

$func Fname Fin = Fout;

то компилятор выполняет проверку, что все входные образцы P1, P2, ..., Pn являются "уточнениями" входного формата Fin, а все хвосты R1, R2, ..., Rn заведомо вырабатывают результаты удовлетворяющие выходному формату Fout.

При записи определений функций разрешается использовать следующие сокращения.

Если в предложении Sntj хвост Rj состоит из одной запятой, его разрешается опускать, в результате чего предложение Sntj принимает вид Pj.

Если определение функции содержит только одно предложение Snt, т.е. имеет вид

Fname \{ Snt; };

его разрешается записывать в сокращенном виде следующим образом:

Fname Snt;

Например, определение функции Sumsq может быть записано следующим образом:

Sumsq sX sY = <"+" <"*" sX sX> <"*" sY sY>>;