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>>;