Программист – Программирование на gforth (страница 7)
Пример отладки:
100 200 300 \ Помещаем три числа в стек
.S \ Выводит: 100 200 300 <3> ok
SWAP \ Меняем местами 200 и 300
.S \ Выводит: 100 300 200 <3> ok
DROP \ Удаляем верхний элемент (200)
.S \ Выводит: 100 300 <2> ok
6. Продвинутые техники
Использование DEPTH
Слово DEPTH (или DEPTH) помещает в стек текущее количество элементов:
1 2 3 DEPTH . \ Выводит 3 (в стеке три элемента)
Это полезно для написания универсальных функций, работающих с переменным количеством аргументов.
Работа с подстеками
В сложных программах удобно мысленно разделять стек на логические части. Например, для вычислений с координатами :
: distance-squared ( x1 y1 x2 y2 -- dist^2 )
\ Вычисляет квадрат расстояния между точками (x1,y1) и (x2,y2)
ROT - SWAP ROT - \ ( dx dy )
DUP * SWAP DUP * + \ dx² + dy²
;
Упражнение для закрепления
Запустите Gforth.
Используя PICK, вычислите выражение (не вводя число 2 дважды).
Определите слово 3DUP, которое дублирует три верхних элемента стека. Протестируйте его на числах 1, 2, 3.
Напишите слово avg-of-three, которое вычисляет среднее арифметическое трёх чисел. Протестируйте на 10, 20, 30 (ожидаемый результат: 20).
Создайте файл stack-utils.fs и сохраните в него определения 3DUP и avg-of-three. Загрузите файл командой include stack-utils.fs и проверьте работу слов.
Используйте .S и DEPTH, чтобы отследить изменения стека на каждом этапе выполнения.
Подсказки: * Решение для п. 2:
2 3 * 2 PICK + . \ 2×3 + 2 = 8
•
Определение
3DUP
:
: 3DUP ( a b c -- a b c a b c )
2 PICK 2 PICK 2 PICK ;
•
Определение
avg-of-three
:
: avg-of-three ( a b c -- avg )
+ + 3 / ;
Если у вас возникли трудности, проверьте: * правильность индексов для PICK/ROLL; * соответствие количества операндов для арифметических операций; * наличие ; в конце определений.
Глава 5. Управление потоком выполнения в Gforth
В этой главе разберём конструкции управления потоком выполнения в Gforth: условные операторы и циклы.
Базовая конструкция условного перехода в Forth:
условие IF true-блок ELSE false-блок THEN
Как это работает: * условие — выражение, оставляющее флаг в стеке (-1 для true, 0 для false); * если флаг true, выполняется true-блок; * если false, выполняется false-блок (если он есть); * THEN завершает конструкцию.
Операторы сравнения возвращают флаг: * = — равно; * <> — не равно; * > — больше; * < — меньше; * >= — больше или равно; * <= — меньше или равно.
Пример 1: простое условие
: is-zero ( n -- )
0= IF ." Число равно нулю" ELSE ." Число не равно нулю" THEN
CR ;
Проверка:
0 is-zero \ Вывод: Число равно нулю
5 is-zero \ Вывод: Число не равно нулю
Пример 2: чётность числа
: even? ( n -- flag )
2 MOD 0= ;
: check-even ( n -- )
even? IF ." Чётное" ELSE ." Нечётное" THEN
CR ;
Проверка:
4 check-even \ Вывод: Чётное
7 check-even \ Вывод: Нечётное