Язык РЕФАЛ: первичные функции и примеры составления программ
Первичные функции
Во многих случаях возникает необходимость в функциях, которые не могут быть описаны средствами Рефала. К ним прежде всего относятся функции операций ввода/вывода, осуществляющие связь со внешним миром. Помимо этого, такими функциями являются ряд функций арифметических и логических операций, а также функции работы с особыми видами памяти Рефала. Эти функции пишутся обычно на других языках и называются первичными. С точки зрения работы Рефал-машины исполнение вызова первичной функции осуществляется за 1 шаг ее работы.
Функции ввода/вывода
Функции ввода/вывода предназначены для организации диалогового взаимодействия между пользователем и программой. Для ввода строки с клавиатуры используется функция card. Для вывода информации на экран используются операции print, prout, которые различаются возвращаемым значением и способом представления информации на экране. Ввод/вывод может быть переназначен в произвольный файл стандартным образом.
Функция card осуществляется вызовом
k/card/ .
и дает возможность читать строку символов из входного потока. После вызова функции программа переходит в состояние ожидания ввода строки. По окончании ввода строки следует нажать клавишу "Enter". Возвращаемым значением является введенная строка.
Функция print осуществляется вызовом
k/print/ <E>.
где E - произвольное рефал-выражение (возможно, и пустое), и выводит c новой строки это выражение. При пустом выражении пропускается 1 печатная строка. При непустом выражении символы-литеры выводятся в виде соответствующих литер, структурные скобки выводятся как круглые скобки, а составные символы выводятся с ограничителями ' вместо "/". Возвращаемым значением является выводимое выражение.
k/print/ 'функция'(/f1/).
'функция'(/f1/).
При этом на устройство вывода будет выдана строка
'функция'('f1') ,
Функция prout осуществляется вызовом
k/prout/ <E>.
где E - произвольное рефал-выражение (возможно, и пустое), и выводит c новой строки это выражение. Отличием от функции print является то, что всегда возвращается пустое выражение.
Арифметические функции
Функции работают только с целыми числами, каковыми являются в представлении Рефала - символы-числа с возможно предшествующим знаком минус '-'. Например, '-'/7/, /0/, /2007/. Нуль представляется либо нулевым символом-числом, либо пустым выражением.
Все арифметические функции допускают использование пустого выражения в качестве аргумента и воспринимают его как нуль.
К арифметическим функциям относятся:
- add - сложение;
- mul - умножение;
- sub - вычитание;
- dr - деление нацело с остатком;
- div - деление нацело;
- p1 - инкремент (увеличение на 1);
- m1 - декремент (уменьшение на 1).
Для преобразования целых чисел в символьный вид и обратно используются функции symb и numb.
Функции add, mul, sub осуществляются вызовом
k/op/ (<N1>) <N2>. ,
где op - одна из операций add, mul, sub, а N1 и N2 - макроцифры. Этот вызов возвращает макроцифру (для положительного результата знак '+' не ставится) суммы, произведения или разности N1-N2 в зависимости от операции. Например, следующие вызовы функции приведут к таким результатам:
k/add/ ('-'/5/) /3/. -> '-'/2/ k/add/ () /2/. -> /2/ k/mul/ ('-'/5/) /3/. -> '-'/15/ k/mul/ (/2/). -> /0/ k/sub/ ('-'/5/) /3/. -> /8/ k/sub/ () /2/. -> '-'/2/
Функция dr осуществляется вызовом
k/dr/ (<N1>) <N2>. ,
где N1 - делимое, а N2 - делитель. Она возвращает выражение
<Q> (<R>) ,
где Q - частное, а R - остаток. Попытка делить на 0 приводит к аварийному завершению. Знаки частного и остатка определяются следующим образом: сначала производится деление нацело без учета знаков делимого и делителя, а затем частному и остатку приписываются знаки так, чтобы выполнялось соотношение:
N1 = Q*N2 + R
т. е. остаток (не равный нулю) всегда имеет знак делимого, а знак частного определяется знаками делимого и делителя (при одинаковых положителен, при разных отрицателен). Например, следующие вызовы функции приведут к таким результатам:
k/dr/ (/5/) /3/. -> /1/ (/2/) k/dr/ (/5/) '–'/3/. -> '–'/1/ (/2/) k/dr/ ('–'/5/) /3/. -> '–'/1/ '–'(/2/) k/dr/ ('–'/5/) '–'/3/. -> /1/ '–'(/2/)
Функция div в отличие от функции dr возвращает только частное. В остальном же подобна ей. Например, следующие вызовы функции приведут к таким результатам:
k/div/ (/5/) /3/. -> /1/ k/div/ (/5/) '–'/3/. -> '–'/1/ k/div/ ('–'/5/) /3/. -> '–'/1/ k/div/ ('–'/5/) '–'/3/. -> /1/
Функции p1, m1 имеют 1 аргумент и возвращают соответственно макроцифру, увеличенную на 1 или уменьшенную на 1. Например, следующие вызовы приведут к таким результатам:
k/p1/ '–'/2007/. -> '–' /2006/ k/p1/. -> /1/ k/m1/ /2007/. -> /2006/ k/m1/. -> '–'/1/
Функция symb преобразует макроцифру (аргумент) в символьное представление. Например, следующие вызовы функции приведут к таким результатам:
k/symb/ '–'/2007/. -> '–2007' k/symb/. -> '0'
Функция numb преобразует цепочку символов (аргумент), являющуюся десятичной записью целого числа в макроцифру этого числа. Например, следующие вызовы функции приведут к таким результатам:
k/numb/ '–2007'. -> '–'/2007/ k/numb/ '0'. -> /0/