Диалекты бейсика для ZX Spectrum 1992 г.

Beta Basic - Процедуры.


ПРОЦЕДУРЫ_

DEF PROC, LOCAL, REF, DATA, READ, READ LINE, ITEM(), END PROC, PROC, LIST PROC

В Beta Basic по сравнению с другими диалектами Бейсика для ZX Spectrum инструмент процедур реализован, пожалуй, наиболее удачно (см. стр. 176, 222).

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

DEF PROC <имя процедуры)

[<список формальных параметров> |DATAj DEFAULT<задание значений формальных параметров по умолчанию) [LOCAL <список локальных переменных и массивов номер 1 >]

< операторы, [READ [LINE ] <переменная>]> (RETURN]

[LOCAL <список локальных переменных и массивов номер N>]

< операторы) [RETURN]

END PROC

<Имя процедуры) может иметь произвольную длину и состоять из любых символов (кроме псевдографики, UDG, символов пробела и ключевых слов), но начинаться оно должно обязательно с буквы.

При этом оно может совпадать с именами переменных как в основной программе, так и в самой процедуре. Блок описания процедуры может находиться в любом месте программы, но оператор заголовка обязательно должен быть первым оператором в строке.

Возврат из процедуры может происходить в любой ее точке по оператору RETURN либо в конце — по END PROC. Оператор END PROC, помимо функции возврата, выполняет еще и роль маркера конца тела процедуры (этим он и отличается от RETURN): если процедура встроена в середину текста основной программы, последняя, наткнувшись на заголовок процедуры, «перепрыгнет» через нее. Точкой «приземления» послужит оператор, следующий за END PROC. Если же интерпретатор не сможет найти конца процедуры, он прервет выполнение программы сообщением No END PROC.

Листинг процедуры может быть выведен на экран отдельно от всей программы оператором

LIST PROC <имя процедуры >

Вызов процедуры осуществляется следующим образом:

[PROC] <имя процедуры) [<список фактических параметров)]

В этих конструкциях полностью отсутствует какая бы то ни была привязка к номерам строк. Эта особенность процедур в сочетании с возможностью принимать данные из основной программы посредством списка параметров позволяет создавать автономные программные модули. Однажды разработанные, они могут быть использованы в других программах практически без изменений. Достигается это объявлением внутренних переменных процедуры локальными, что позврляет уйти от проблемы совпадения их имен в процедуре и основной программе. Причем в Beta Basic (в отличие, например, от Laser Basic и MegaBasic) они действительно «до конца» локальны.

Переменные объявляются локальными с помощью оператора LOCAL, который может располагаться в любом месте процедуры и повторяться с разным списком переменных не один раз. Список представляет из себя перечень имен переменных, разделенных запятыми. Переменная, указанная в LOCAL, теряет свое прежнее значение (если она его до этого имела) и становится неопределенной. Ее можно заново инициализировать и использовать в теле процедуры с новым содержанием. После возврата в основную программу ей будет возвращено прежнее значение.

10 LET А=1 20 PROC Test 30 PRINT A.D: STOP 100 DEF PROC Test

110 LET D=5: LOCAL A: DEFAULT A=10 120 PRINT A.D 130 END PROC

В процедуре Test вводится новая переменная D и объявляется локальной определенная в основной программе переменная А (строка 1 10). Оператор PRINT (строка 1 20) напечатает два числа: 1 0 и 5, что соответствует значениям переменных А и D в процедуре. После возвращения из процедуры оператор PRINT (строка 30) огласит новую обстановку: переменная А без потерь пережила «прогулку» в процедуру и сохранила прежнее значение; переменная D вынесла значение из процедуры, так как не была объявлена в ней локальной.

Кроме переменных, в процедуре можно объявлять локальными и массивы (еще один плюс Beta Basic), после чего их необходимо инициализировать оператором DIM. Процедура, в которой встретятся такие строки:

110 LOCAL A(),S$

120 DIM А( 10,20): DIM S$(5,40)

- создаст два локальных массива: числовой с именем А и символьный с именем S$. Если последний не объявлять как массив, процедура будет воспринимать S$ как простую символьную переменную. Значения, присвоенные в процедуре элементам лбкальных массивов, при возврате из нее будут утрачены, а содержимое одноименных массивов в основной программе восстановлено.

В случае многократного вложения процедур (когда одна вызывает другую, та, в свою очередь, третью и т. д.) объявленные на одном из уровней вложения локальные переменные и массивы могут использоваться всеми процедурами более низкого уровня, оставаясь «невидимыми» для «верхних» процедур.

Как мы уже упоминали, список формальных параметров процедуры указывается после ее имени в операторе-заголовке. Значения формальным параметрам присваиваются посредством приведения в операторе вызова процедуры списка фактических параметров, размещенных через запятую после имени процедуры. Фактические параметры могут быть заданы как-в явном виде, то есть числовыми или символьными константами, так и переменными, элементами массивов, выражениями. Разумеется, все переменные и элементы массивов должны быть определены к моменту вызова процедуры.

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

В общем случае допустимо, чтобы число фактических параметров в операторе вызова процедуры было меньше числа формальных параметров из описания процедуры. При этом «лишние» переменные из заголовка процедуры просто останутся в ней неопределенными. Однако имеется возможность с помощью описанного ранее оператора DEFAULT задать значения пропущенных параметров, которые будут приниматься ими по умолчанию. Если же Вы хотите при вызове процедуры опустить один или несколько фактических параметров, стоящих в середине списка, то место в списке каждого из них необходимо «пометить» лишней запятой.

В том случае, когда вообще невозможно заранее предсказать количество передаваемых в процедуру фактических параметров, список формальных параметров в ее заголовке заменяется одним ключевым словом DATA. Считывание в процедуре значений из такого «резинового» списка необходимо осуществлять оператором

READ. Для того чтобы определить тип очередного элемента данных и обнаружить конец списка, используется функция 1ТЕМ(). Она не имеет параметров и возвращает 1, если в списке параметров следующим стоит символьное значение, 2 — если числовое значение, и «разрешается» нулем при достижении конца списка. Избежать использования кавычек при пересылке строковых значений позволяет ключевое слово LINE, помещаемое в процедуре после READ (например, READ LINE А$)95.

Приведем пример пакета процедур, использующих описанные выше формы приема параметров:

80 DEF PROC Prima DATA: LOCAL А,В,С 90 DO WHILE ITEM()00 100 READ A: READ B: READ С 110 LET 1>=В*В—4*A*C

120 IF D>=0 THEN PROC Real: ELSE PROC Complex

130 LOOP: END PROC

140 DEF PROC Real: LOCAL XI,X2

150 LET X1=(—B+SQR D)/(2*A)

160 LET X2=(-B-SQR D)/(2*A)

170 PROC Root ,X1,X2: REM Первый параметр опущен 180 END PROC

190 DEF PROC Complex: LOCAL Re.lm

200 LET Re=—В/(2*A), lm=SQR ABS D/(2*A)

210 PROC Root 1 ,Re,lm

220 END PROC

230 DEF PROC Root Cmpl,A,B

240 DEFAULT Cmpl=0: PRINT "Roots:",

250 IF Cmpl THEN PRINT "X1=";A;"+";B;"i","X2=";A;"-";B;"i":

ELSE PRINT "X1=";A,"X2—";B 260 END PROC

Этот пакет процедур вычисляет корни Х1 и Х2 квадратного уравнения А*Х f 2+В*Х+С. Процедура Prima в цикле (строка 90) считывает очередные коэффициенты уравнения (строка 100), рассчитывает по ним дискриминант (строка 110) и, в зависимости от его знака, вызывает одну из двух процедур: Real или Complex (строка 120). Каждая их них в свою очередь обращается к процедуре вывода результатов Root. Но значения, передаваемые в эту процедуру, имеют разный смысл: в первом случае это действительные корни уравнения, во втором — действительная и мнимая части сопряженных комплексных корней. Поэтому в процедуру Root передается признак «комплексности» корней Re* в зависимости от его значения, процедура выбирает вариант вывода на экран (строка 250). Обращение к этому пакету может выглядеть, например, так: PROC Prima 3,10,1,1,2,3 Количество параметров при этом должно быть кратно трем.

Beta Basic позволяет не только пересылать значения параметров из вызывающей программы в процедуру, но и принимать из нее результаты расчетов, не прибегая при этом к глобальным переменным. Это достигается nyieM передачи процедуре ссылки на соответствующий фактический параметр. Если при передаче параметров обычным порядком (по значению) в процедуре создается временная область локальных переменных, в которую и копируются значения фактических параметров, и которая уничтожается при возврате из процедуры, то при передаче значения по ссылке процедура «получает в руки» лишь указатель на соответствующий фактический параметр (его адрес в основной области переменных). Работая с таким локальным параметром-ссылкой, процедура фактически напрямую «общается» с соответствующей переменой из основной программы, лишь «называя» ее своим, локальным именем. Все изменения, производимые с такой локальной переменной, автоматически отражаются на содержимом ее прообраза из вызывающей программы. Для указания того, что передача параметра производится по ссылке, используется ключевое слово REF (reference), которое помещается перед каждым соответствующим формальным параметром в заголовке процедуры:

10 LET А=5, В=10, Х=1, Y=2: PRINT A,B,X,Y 20 PROC Test А,В: PRINT A,B,X,Y 40 DEF PROC Test REF X, REF Y: LOCAL Z 50 LET Z=X, X=X+Y, Y=Z*Y 60 END PROC

В этом примере все действия, производимые в процедуре над локальными переменными X и Y, приводят к изменению соответствующих им переменным А и В: значения последних, выводимые операторами PRINT до вызова процедуры и после нее, будут различными, в то время как переменные X и Y в основной программе не изменятся, несмотря на то, что одноименные им переменные были использованы в процедуре.

Такой способ пересылки параметров позволяет передавать процедуре массивы, указывая после REF их имена с пустыми скобками. Налицо серьезная экономия памяти: процедура не создает копии массива, а работает с оригиналом, лишь пользуясь его локальным «псевдонимом».

При обращении к процедуре можно опускать служебное слово PROC, таким образом фактически расширяя арсенал операторов Beta Basic. К примеру, можно написать собственную процедуру с именем BOX, рисующую на экране прямоугольник, и обращение к ней по синтаксису ничем не будет отличаться от аналогичных операторов, скажем, CIRCLE. Заметим однако, что эта особенность интерпретатора может сыграть с программистом злую шутку: поскольку имя процедуры может состоять практически из любого набора символов, редактор Beta Basic способен «проглотить» какую-нибудь синтаксически неверную строку, приняв ее за экзотическое имя процедуры.

Beta Basic допускает рекурсию (обращение процедуры к самой себе) практически неограниченное количество раз. Но на практике, вследствие переполнения стека адресов возврата и «размножения» локальных областей переменных, количество рекурсий едва ли с может превысить несколько сотен (при этом скорость работы программы значительно снижается). Этого эффекта можно избежать, если все параметры в рекурсивную процедуру передавать по ссылке.




СОДЕРЖАНИЕ:
  1. Laser Basic - Вывод спрайтов на экран; Вывод на экран части спрайта; Перенос атрибутов; Преобразование окна экрана; Наборы переменных; Перемещение спрайтов; Наложение спрайтов; Копирование изображения с экрана в спрайт; Преобразование спрайтов; Скроллинг пейзажа; Изменение размеров области спрайт-файла; Вспомогательные графические операторы и функции; Определение столкновений спрайтов; Сервисные операторы и функции; Процедуры; Загрузка и запись программ.


  Оставте Ваш отзыв:

  НИК/ИМЯ
  ПОЧТА (шифруется)
  КОД



Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
От авторов - вот уже и второй номер. Интересно, сколько их еще будет?
Werewolf - Зверь из Жеводана.
СС'99 - интервью: Random/CC (отмазки о слабой орагнизации СС'99).
Разберемся - Письмо американского программиста.
Проходилка - рохождение очень интересной, но довольно трудной игры " 48 УТЮГОВ ".

В этот день...   29 марта