Область дії означень та побічний ефект
Будемо говорити, що програма або підпрограма охоплює підпрограми, записані в ній, і що вони вкладені в неї. Наприклад, програма twovars охоплює процедури plus і minus (і вони обидві вкладені в неї), а процедура plus охоплює minus. З правила, яким задається область дії означення, випливає, що ім'я в підпрограмі відповідає найближчому з його означень, записаних вище в підпрограмі або підпрограмах, що її охоплюють, зокрема, в програмі.
Звідси одразу маємо відповіді на питання, поставлені спочатку: у підпрограмі можна використовувати ім'я, означене в підпрограмі, що її охоплює, або програмі, але не можна використовувати ім'я, означене не вище в блоці або не в підпрограмі, що її охоплює.
Основний практичний висновок з цих правил – намагатися уникати вкладених підпрограм і прагнути до того, щоб усі підпрограми були вкладені тільки в програму, тобто щоб у них не було своїх підпрограм.
У цьому розумінні програма twovarst явно невдала.
Означення підпрограми починаються з її параметрів, а якщо їх немає, то з початку блоку. Тому підпрограма іменується не в ній самій, а в програмі, або, в гіршому випадку, в підпрограмі, що її охоплює. Звідси випливає, що означення імені підпрограми діє до кінця блоку, в якому її записано. Тому її можна викликати в інших підпрограмах, записаних нижче в цьому ж блоці.
Приклад 7.2. Раціональне число подається нескоротним дробом A/B, де B>0. Сумою двох дробів A/B і C/D є результат скорочення дробу (AD+BC)/BD. Напишемо програму, у якій описується читання двох дробів, їх додавання зі скороченням результату й виведення у вигляді нескоротного дробу. Будемо припускати, що знаменники дробів, що читаються, не рівні 0.
Опис дій із дробами оформимо у вигляді підпрограм: читання readfr, додавання plusfr і друкування writefr. Закінчення fr в іменах процедур – це скорочене fraction, тобто "дріб".
У програмі означимо цілі змінні a, b, c, d, r1, r2 для зберігання прочитаних дробів a/b і c/d та результату операції r1/r2. Не уточнюючи самих підпрограм, запишемо поки лише тіло програми з їх використанням:
begin
writeln('задайте дріб (два цілих, друге не 0):'); readfr(a, b);
writeln('задайте дріб (два цілих, друге не 0):'); readfr(c, d);
plusfr(a, b, c, d, r1, r2);
writefr(r1, r2);
end.
А тепер почнемо уточнювати підпрограми. Процедура читання очевидна:
procedure readfr(var x, y : integer);
begin readln(x); readln(y) end;
Передбачається, що при виконанні програми користувач набере дві цілі сталі.Процедура додавання повинна повертати результат додавання у вигляді нескоротного дробу. Нехай її параметри x1, y1, x2, y2 задають два дроби, що додаються, а x3, y3 – результат. Скорочення дробу задамо процедурою redufr. Її параметри-змінні задають дріб (скорочений спочатку і в результаті). Тоді додавання задається такою процедурою:
procedure plusfr(x1, y1, x2, y2 : integer; var x3, y3 : integer);