Барсикиана,
или
Опыт научно-фантастического программирования

В.Ф.Очков

(журнал «Компьютеры в учебном процессе», № 1, 1996)

Вы думаете, я знаю Бейсик? Нет, я не имел счастья воспользоваться таким воспитанием. Мой отец был мерзавец, скотина. Он и не думал выучить меня Бейсику. Я был тогда еще ребенком, меня легко было приучить – стоило только посечь хорошенько, и я бы знал, я бы непременно знал.

Почти Н.Гоголь

Научно-фантастическая литература питает мир новыми идеями. Далеко не все из них потом реализуются. Но каждая заслуживает того, чтобы над ней задумались и измерили линейкой со шкалой, на одном конце которой стоит метка «Дурацкая», а на другом «Гениальная» («Безумна-Логична», «Безобразна-Красива», «Бесполезна-Практична» и т.д.)

Автор предлагает читателям подойти с этими мерками к помещенным в статье программам, написанным на языке БаРсик (BaRsic), где Р означает «расширенный» Бейсик (немного путано, но благозвучно).

Некоторые из нижеописанных программистских fiction-конструкций читателю покажутся совсем уж... не подберу подходящего слова. Но вспомним классический парадоксальный вопрос «А достаточна ли безумна ваша гипотеза, чтобы она могла стать теорией?»

 Пример 1

В языке Бейсик есть конструкции, обладающие свойством, которое с некоторой долей условности можно назвать полиморфизмом: одно и тоже ключевое слово меняет свой смысл в различных программных сюжетах. Так, например, знак «=» будет и символом присвоения (A = B + C) и оператором сравнения (IF A = B THEN...). Другой пример - ключевые слова MID$ и TIME$, которые согласно документации по языку отмечают и встроенную функцию, и оператор языка:

A$ = MID$("COMPUTER", 3, 3) ' Здесь MID$ - функция

MID$(A$, 2, 1) = "$$$" ' Здесь MID$ - оператор

StartTime$ = TIME$ ' Здесь TIME$ - функция

TIME$ = "12:30" ' Здесь TIME$ - оператор

Второй пример не совсем правомерен - TIME$ можно считать не функцией и не оператором, а системной переменной.

Когда ключевое слово MID$ стоит в правой части оператора присвоения, то оно означает встроенную функцию. Если же MID$ окажется в левой части, то оно превращается в оператор. Из-за такой особенности MID$ можно назвать двухсторонней встроенной функцией - функцией, способной не только возвращать соответствующее значение, но принимать его. Это нововведение есть на языке Барсик. Так Барсик-оператор:

SIN(X) = 0.2

не будет содержать синтаксической ошибки: здесь синус - двухсторонняя функция. Переменной X будет присвоено значение арксинуса 0.2. Только и всего.

Как понимает читатель, такое расширение языка Бейсик дает возможность очень просто решать уравнения. Здесь может быть подводный камень, связанный тем, что число корней уравнения может быть больше одного. Но эту сложность легко обойти.

Во-первых, встроенная функция SQR возвращает не два значения (плюс-минус квадратный корень), а одно. И никого это не смущает. Арктангенс же вообще должен возвращать бесчисленное множество значений, но возвращает опять же одно - положительное и ближайшее к нулю. И это опять никого не шокирует. Если у уравнения корней много, то нужно договориться, какой именно корень следует искать. Можно также по ходу счета преобразовать простую переменную в одномерный одноименный массив (вектор) и записывать в него все найденные корни. Но проще искать корень, ближайший к опорной точке.

Так строка Барсика:

X = 1: X ^ 2 = 4: PRINT X

выдаст на печать двойку, а строка:

X = -1: X ^ 2 = 4: PRINT X

минус двойку.

На Барсике можно решать даже системы уравнений. Пример:

Листинг 1

' Программа решения системы алгебраических уравнений

' на языке BArSIC (r - Решающий)

' Исходные данные

G = 20: a = 1: b = 1: alfa = 30*3.14/180

' Первое приближение

P = G: Y = G: X = G

GIVEN

            P * SIN(alfa) = X

            Y + G = P * COS(alfa)

            P * b = G * (a + b) * COS(alfa)

FIND(X, Y, P)

' Вывод корня системы

PRINT "X="; X, "Y="; Y, "P="; P

Запуск такой программы выдаст на дисплей решение (X, Y и P) системы трех алгебраических уравнений, зажатых между ключевыми словом GIVEN и встроенной функцией FIND. Такой метод решения систем применяется в математическом пакете MathCAD фирмы MathSoft.

 Пример 2

Из пакета MathCAD в язык Барсик перекочевал и другой интересный прием, которого так не хватает нормальному Бейсику - задание числовым переменным не только определенного типа (INTEGER, LONG, SINGLE, DOUBLE и CURRENCY), но и размерности: килограмм, метров, секунд и т.д.

Что-то подобное уже есть в Бейсике, где переменная может "заглатывать" и свое значение и свой тип: Int_A = 20%, Lng_B = 1&, Sng_C = 2.2!, Dbl_D = 3.3# и Crn_Е = 4.4@, опираясь на суффиксы (20%, &, !, # и @). Единицы измерения стоимости (рубли, доллары, марки и т.д.) в нормальный Бейсик уже косвенно введены, если вспомнить о типе CURRENCY.

Листинг 2

' Программа решения системы алгебраических уравнений

' на языке BArSIC (r - Размерный)

' Исходные данные

G = 20 * Newton ' Здесь Newton не переменная, а размерность силы

a = 1 * m ' m - размерность длины

b = 1 * m

alfa = 30 * deg ' deg - размерность угла

' Первое приближение

P = G: Y = G: X = G

GIVEN

            P * SIN(alfa) = X

            Y + G = P * COS(alfa)

            P * b == G * (a + b) * COS(alfa)

FIND(X, Y, P)

' Вывод корня системы

PRINT "X="; X, "Y="; Y, "P="; P

Ввод размерности позволит выдавать на дисплей значения переменных с соответствующей размерностью. Вот что появиться на дисплее после выполнения вышенаписанной программы 3:

X= 17.321 * Newton                Y= 10 * Newton             P= 34.641 * Newton

Но главное, вводом размерности можно контролировать правильность написания выражений и препятствовать тем самым складыванию метров с килограммами, например.

Контроль типа переменной в той или иной степени ведется во всех языках программирования. Некоторые версии Бейсика запрещают писать Sgn_A! = Dbl_B# + Lng_C&, например. В более новых версиях такой оператор присвоения уже допустим. Более того, в Visual Basic введен новый тип переменных VARIANT, позволяющий перемешивать даже числовые и литерные переменные - A = "123" + 123 и никакой ошибки [2].

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

 Пример 3

Листинг 3

' Программа игры "Угадай число"

' на языке BArSIC (r - Рвущий циклы)

RANDOMIZE TIMER - 32767

PRINT "Угадай число от 1 до 1000"

A = 1 + INT(1000 * RND(1))

I = 0 ' Счетчик тактов цикла

INPUT "Время на отгадывание (сек) "; DeltaTime

TimeStart = TIMER ' Фиксация начального момента времени

DO WHILE SINE LOCO (TIMER - TimeStart <= DeltaTime, PRINT "Поздно")

I = I + 1

PRINT I; "-я попытка";

INPUT B ' Этот оператор мог бы ломать правила игры,

' если бы не цикл SINE LOCO

IF A = B THEN PRINT "Угадали": EXIT DO

IF B < A THEN PRINT "Недолет" ELSE PRINT "Перелет"

LOOP ' Конец цикла и по месту и повремени

END

Программа 4 позволяет сыграть с машиной в нехитрую игру "Угадай число", когда компьютер загадывает целое случайное число в диапазоне от 1 до 1000, а человек его отгадывает за минимум попыток. В традиционных языках программирования цикл прерывается только в определенном месте тела (цикл с предпроверкой, цикл с постпроверкой, цикл с выходом из середины). Но часто бывает необходимо, как, например в нашей игре, выходить из любого места цикла по сигналу за пределами цикла. Цикл догадок (DO... LOOP) на Барсике имеет два выхода: один традиционный - по месту в алгоритме (IF... THEN... EXIT DO), а второй - необычный - без места (SINE LOCO), управляемый булевой переменной, меняющейся вне цикла. Дело в том, что оператор INPUT B в программе 4 не подчиняется правилам игры, отграничивающими время на поиск задуманного машиной числа. Прервать выполнение этого оператора и выдать на дисплей сообщение "Поздно" в силах только цикл SINELOCO.

Пример 4

Программисты часто попадают впросак, из-за того, что считают, что у альтернативного вопроса может быть только два ответа. А это не так.

Читатель, задайте товарищу альтернативный вопрос ("Ты идешь в кино?", например) и вы получите не два, а как минимум три варианта ответа ("Да.", "Нет." и "Не знаю."). Уход от вопроса - это тоже ответ. Что-то подобное можно наблюдать и при анализе логических выражений, используемых в программировании для управления работой вычислительной машины. Кроме двух известных значений (Да - Нет, Ненуль - нуль, True - False) есть и третье, когда значение этих выражений неопределенно. Такая ситуация может рассматриваться не только как грубая ошибка, но и как тонкий программистский прием, опирающийся на метод проб и ошибок: если логическое выражение не определено, то выполнение программы идет по новому, третьему пути. Аналогичную картину можно наблюдать и в поведении двоичных элементов памяти компьютера - конденсатор, триггер, участок магнитного или оптического диска, дырка на перфокарте или на перфоленте. Кроме двух базовых состояний (заряжен - разряжен, открыт - закрыт, намагничен - размагничен, проколот-непроколот), генерирующих бит информации, есть и третье - недостаточно заряжен, вышел из строя, плохо намагничен, порван. Компьютер был бы просто неработоспособен, если б его элементарная база опиралась только на двоичный код. Машина должна правильно анализировать ход обработки информации (а для этого и существуют контрольные байты и другие хитрости) и ожидать не два, а три варианта ответа на альтернативный вопрос: "Да.", "Нет." и "Спроси у кого-нибудь другого." или что-то в этом роде.

Листинг 4

' Программа "Экстрасенс"

' на языке BArSIC (r - Реальный)

PRINT "Действуют ли на Вас экстрасенсы ?"

DO ' начало диалога человека с машиной

INPUT "Когда Вы родились (ГГГГ.ММ.ДД)"; D$

IF D$ > "1894.04.01" AND D$<"1995.04.01" THEN EXIT DO

PRINT "Вы что, меня за дурочку принимаете?!"

PRINT "Повторите ввод!"

LOOP ' конец начального диалога, далее процесс расчета

D = VAL(RIGHT$(D$,2))

Y = VAL(LEFT$(D$, 4))

P$ = STR$(D * 12 * Y)

S = 0: FOR I=1 TO LEN(P$): S=S+VAL(MID$(P$,I,1)): NEXT

IF S > 1 + VAL(LEFT$(D$, 2)) THEN ' начало тринативы

PRINT "Действуют."

ELSE PRINT "Слава Богу, не действуют."

NO THEN NO ELSE PRINT "На вас никто и ничто не действует."

END IF ' конец тринативы

В Бейсике как и в любом другом процедурном языке есть две основные структурные управляющие конструкции - цикл и альтернатива, реализующие Дейкстровскую триаду: следование - повторение - выбор. Барсик кроме этого вооружен тринативой, проиллюстрированной программой 4. Тринатива, в отличие от альтернативы (IF... THEN... ELSE...), имеет не два (alter - второй), а три плеча, что более соответствует реальным ситуациям, моделируемым на компьютере.

Пример 5

Листинг 5

' Программа решения задачи о рыбном ряде Дирака

' на языке BArSIC (r-Русифицированный)

' Исходный текст программы

INPUT "Число рыбаков"; Fishers

INPUT "Дельта рыб "; DeltaFish

INPUT "Начальное число рыб"; NumFish

LET NumFish = NumFish + 1

DO

LET NumFish = NumFish - 1

LET Flag$ = "up"

LET Fish = NumFish

FOR Fisher = 1 TO Fishers

LET Fish = Fish + DeltaFish

LET Fish = Fish - Fish / Fishers

IF Fish > INT(Fish) THEN LET Flag$ = "down": EXIT FOR

NEXT

LOOP WHILE Flag$ = "down"

PRINT "Ответ "; NumFish

END

' Текст программы, переведенный на русский язык

ВВОД "Число рыбаков"; Рыбаки

ВВОД "Дельта рыб "; ДельтаРыб

ВВОД "Начальное число рыб"; ЧислоРыб

ПУСТЬ ЧислоРыб = ЧислоРыб + 1

ДЕЛАЙ

ПУСТЬ ЧислоРыб = ЧислоРыб - 1

ПУСТЬ Флаг$ = "поднят"

ПУСТЬ Рыба = ЧислоРыб

ДЛЯ Рыбак = 1 К Рыбаки

ПУСТЬ Рыба = Рыба + ДельтаРыб

ПУСТЬ Рыба = Рыба - Рыба / Рыбаки

ЕСЛИ Рыба > INT(Рыба) ТОГДА ПУСТЬ Флаг$ = "опущен": ВЫХОД ДЛЯ

СЛЕДУЮЩИЙ

ЦИКЛ ПОКА Флаг$ = "опущен"

ВЫВОД "Ответ "; ЧислоРыб

АМИНЬ

Многие отечественные программисты не довольствуются тем, что система меню и подсказок среды программирования QBasic в составе локализованной версии MS-DOS 5.0 и MS-DOS 6.0 переведена на русский язык, и сетуют на то, что ключевые слова, операторы и функции этого языка по-прежнему английские. Перевод программ с английского на русский возможно, например в среде Framework2 (Информонтаж). В среде DOS нельзя также использовать русские буквы в именах переменных, процедур и функций. На языке Барсик (если отдать соответствующую команду) можно получить русский перевод текста программы. На листинге 6 показана такая программа, решающая известную задачу о рыбном ряде Дирака. "Три рыбака легли спать, не поделив улова. Проснувшийся ночью первый рыбак решил уйти, взяв свою долю. Но число рыб не делилось на три. Тогда он выбросил одну, а из остатка забрал треть. Второй и третий рыбаки поступили аналогичным образом. Спрашивается, какое наименьшее количество рыб может удовлетворить условию задачи".

Поль Дирак был мастер давать разным существительным приставку "анти" - античастица, например. И в этой задаче он, по-видимому, не изменил своей привычке, оригинально решив ее: минус две рыбы. Выбрасываем одну - получаем минус три, забираем одну - получаем минус две и т.д. Но в ответ вкралась ошибка, которую можно объяснить только, наверное, тем, что у Дирака не было компьютера.

Расчет по программе 6 дает не одно, а целый ряд решений задачи:

..., -110, -83, -56, -29, -2, 25, 52,...

Никто не будет спорить, что минус 29, а тем более минус 110 меньше, чем минус 2. Да, жаль, что у Дирака не было компьютера.

Задачу о рыбаках и рыбках можно решить намного быстрее, чем это сделано по программе 6. Для этого за опорную точку, от которой ведется приближение к ответу, нужно взять не начальное число рыб в улове, а остаток от улова, достающийся последнему рыбаку. Вот как, например, будет выглядеть рыбный ряд Дирака при пяти рыбаках, каждый из которых перед своим уходом по-английски выбрасывает по одной рыбке:

... -6254/-2052, -3129/-1028, -4/-5, 3121/1020, 6246/2041...

Этот ряд (числитель - начальный улов, знаменатель - остаток для последнего рыбака) подсказывает более быстрый алгоритм решения задачи Дирака, чем заложенный в программу 6: за остаток рыб для последнего рыбака берется единица, а потом к ней прибавляется по единице, если условие дележа не выполняется. Но в этом случае, хоть задача и будет решена быстрее, антирыб не получится: Дирак перешагнул нуль по своей гениальности, а машина, работая по программе 6, - по своей "наивности", не нарушенной приемами оптимизации. "Описывай, не мудрствуя лукаво, Все то, чему свидетель в жизни будешь..." - советовал отец Пимен Григорию Отрепьеву, наставляя его в искусстве летописи. KISS-принцип искусства программирования требует, чтобы поставленная задача решалась наиболее простыми алгоритмическими приемами. С поцелуями термин KISS ничего общего не имеет, хотя хорошее отношение к компьютеру в нем просматривается. KISS - это аббревиатура английской фразы "Keep it simple, stupid - Делай это проще, дурачок!", призывающей решать задачи более простыми методами и прибегать к изощренным алгоритмам и программным средствам только в крайнем случае. Нужно всегда помнить, что любой наисложнейший алгоритм машина с помощью транслятора сведет к комбинации полусотни простейших операций, которым обучен ее процессор. Чем проще алгоритм, тем быстрее и эффективнее машина это сделает. Попытки ускорить счет или сэкономить память хитрыми приемами не только чреваты ошибками, но и могут привести к обесцениванию результата.

Пример 6

Листинг 6

' Программа "Пароль" на языке

' BArSIC (r - сообРазительный)

DIM Slovo AS WORD_FROM_POCKET

DO ' цикл запроса пароля

PRINT "Ваш пароль ?": A$ = ""

FOR I = 1 TO 10 ' Запрос 10 байт

DO: B$ = INKEY$: LOOP WHILE B$ = ""

A$ = A$ + B$

NEXT I

IF A$ = "СЕМНАДЦАТЬ" THEN EXIT DO

'Машина полезла в карман за словом

GET_FROM_POCKET(Slovo)

PRINT Slovo ' Вывод реплики машины

LOOP ' далее продолжение программы

POCKET ' карман компьютера

"Статьи писать каждый может, а ты вот

попробуй пароль отгадать."

"Рад познакомиться.",

"А мы вас тут давно ждали.",

"Ты опять здесь, подлый трус.",

"Товарищи! Уберите скорее

этого человека от меня.",

"Не жми на эту клавишу,

балда, жми на другую !",

"Ой, щекотно !", "А ты кто такой ?"

' Свободное место в кармане

END POCKET

Традиционный оператор Бейсика INKEY$, использованный в программе 7, существенно обогащает диалог человека с компьютером. Работая по программе с оператором INKEY$, компьютер может делать два дела одновременно: обрабатывать очередные операторы и как бы прислушиваться к человеку, передавая управление программой на новые участки, как только человек нажмет оговоренную клавишу клавиатуры. Так и вежливый, внимательный человек, ведя свой монолог, прислушивается к собеседнику, давая ему возможность при первой необходимости вставить свою фразу или задать уточняющий вопрос.

На языке Барсик появилась еще большая дружественность. Программисты знают, что коммерческий успех программы зависит не только от алгоритма, в нее заложенного, не только от степени оптимизации, но и от удачных фраз, поддерживающих диалог человека с машиной. Здесь имеют фору те программисты, о которых говорят, что они «в карман за словом не лезут». Барсику еще далеко до таких программистов - он в таких ситуациях пока еще "лезет за словом в карман", что и отображено на листинге 7 в программе запроса пароля. Такой "карман" достаточно "отпороть" от программы 7 и «пришить» к новой программе, чтобы обогатить заложенный в нее диалог. Программисту остается только дополнять содержимое «кармана» фразами, подслушанными в очередях, на транспорте и в других «веселых» местах. При прогонке программы с «карманом» Барсик-интерпретатор, опираясь на новый тип литерной переменной WORD_FROM_POCKET, сам «выудит» из «кармана» нужный комментарий, учитывая конкретный момент диалога, обидчивость собеседника, наличие у него чувства юмора.

Введенный в Барсик новый тип переменной WORD_FROM_POCKET открывает новое направление в программировании - субъектно-ориентированное программирование (СОП), которое в отличие от объектно-ориентированного программирования (ООП) оперирует не объектами программы, а субъектами программирования - людьми, ведущими диалог с компьютером.

Конкретная реализация в языке Барсик субъектно-ориентированного программирования - это набор системных переменных, хранящих данные о человеке, сидящем за компьютером. Так переменная USER_NAME$ - хранит имя пользователя программы, USER_OLD% - его возраст и т.д. Опрашивая эти переменные, компьютер знает, кто с ним работает, и поступает соответствующим образом.

Пример 7

Листинг 7

SWITCH ON COMPUTER ' Включаем компьютер,

SWITCH OFF SWET V KOMNATE ' включаем свет в комнате

' Программа поиска простых чисел

' по алгоритму DO-DO-DO (давай-давай-давай)

' на языке BArSIC (r - Рачительный)

K=10000: DIM P%(K): P%(1)=2: N=1: I=1

DO ' давай

            DO ' давай

                        N = N + 2

                        S = INT(SQR(N))

                        J = 0

                        DO ' давай

                                   J = J + 1

                                   P = P%(J)

                        LOOP UNTIL P >= S OR N / P=INT(N/P)

            LOOP UNTIL N / P > INT(N / P)

             I = I + 1

             P%(I) = N

            LOOP UNTIL I = K

SWITCH ON PRINTER ' включаем принтер

FOR I = 1 TO K: LPRINT I, P%(I): NEXT

SWITCH OFF PRINTER ' выключаем принтер

SWITCH ON DISK ' включаем дисковод

OPEN "DATA" FOR OUTPUT AS #1 ' открываем файл

FOR I = 1 TO K: PRINT #1, I, P%(I): NEXT

CLOSE ' закрываем файл

SWITCH OFF DISK ' выключаем дисковод

SWITCH OFF SWET V KOMNATE ' гасим свет в комнате

SWITCH OFF COMPUTER ' выключаем компьютер

По программе 8 отыскиваются первые 10 000 простых чисел. Начинающие программисты, совершенствуя своем мастерство, оптимизируют такую программу так, чтобы они были короче, работали быстрее и чтобы найденные простые числа занимали меньше места в памяти компьютера. Язык Барсик своими операторами SWITCH ON - SWITCH OFF позволяет потренироваться и в экономии электроэнергии, идущей на работу компьютера, его периферии, на освещение рабочего места программиста.

Пример 8

Наверно мало кому из читающих эти строки довелось работать на компьютерах типа БЭСМ, Урал или Мир. А уж о ламповых, релейных или пневматических вычислительных машинах и говорить не приходится. Современные персональные компьютеры помимо всего прочего отличаются от вышеназванных и тем, что работают почти бесшумно. Только легкое жужжание вентилятора да пощелкивание винчестера, качающего информацию с магнитного диска в ОЗУ, радует слух программиста или огорчает его, сообщая, что все хорошо или что-то не так. Шум старых машин был более информационно насыщен. Водились программисты (операторы ЭВМ), которые по характеру гудения машины определяли, в какой стадии находится вычислительный процесс. "Вот, вошли во вложенный цикл!", "Тише! Берется квадратный корень!" - поговаривали они то ли в шутку, то ли всерьез, разыгрывая наивных посетителей вычислительного центра. Но одно можно было утверждать с уверенностью, - на слух состояние машины (исправна - неисправна) можно было определить довольно точно.

Ностальгия по старым временам, наличие у персонального компьютера звукогенератора, а в современных языках - звуковых операторов толкают к идеи озвучивания немых программ. Если в начале и конце самостоятельных программных фрагментов поместить звуковые операторы, да так, чтобы высота звука была связана с типом озвучиваемого фрагмента, а его длительность - с глубиной вложения, то прогонка программы породит мелодию... Можно закрыть глаза, вытянуть ноги, закинуть руки за голову и вспомнить о добрых старых временах... Звукогенератор обладает буфером, - программа уже выполнена, а мелодия звучит подобно свету угасшей звезды...

Листинг 8

' Программа "Сортировка" на языке

' BArSIC (r - Разговорчивый)

PLAY "c1" ' Начало программы

DATA 5,3,-6,-69,-89,-5: REM Исходный массив чисел

READ N: DIM A(N)

FOR I = 1 TO N: READ A(I): NEXT: Flag = 1

PLAY "d1" ' Начало цикла "пока"

WHILE Flag = 1

            PLAY "c2" ' Начало функционального блока

            Flag = 0

            PLAY "c2" ' Конец функционального блока

            PLAY "g2" ' Начало цикла с параметром

            FOR I = 2 TO N

                        PLAY "e3" ' Начало альтернативы

                        IF A(I) < A(I - 1) THEN

                                   PLAY "c4" ' Начало функционального блока

                                   SWAP A(I), A(I - 1): Flag = 1

                                   PLAY "c4" ' Конец функционального блока

                        END IF

                        PLAY "e3" ' Конец альтернативы

            NEXT

            PLAY "g2" ' Конец цикла с параметром

WEND

PLAY "d1" ' Конец цикла "пока"

PLAY "c1"

FOR I = 1 TO N: SPEAK A(I): NEXT 'Выговариваем массив

PLAY "c1" ' Конец программы

Известно, что искусство программирования заключается не столько в умении писать программы, сколько в умении отыскивать в них ошибки. Некоторые программисты обладают особым чутьем на такую специфическую ошибку, как зацикленность программ. Работая в среде Барсика, для отладки программист может опираться не только на свое "обоняние", но и... Барсик программа 9 сортировки массива чисел отлаживается на слух. Для этого в программу командой TRACE SOUND ON введены музыкальные операторы PLAY, озвучивающие начала и концы структурных блоков. Высота звуков отмечает вид управляющей конструкции ("c-до" - функциональный блок, "d-ре" - цикл "пока", "e-ми" - альтернатива, "g-фа" - цикл с параметром, "h-соль" - цикл "до", "a-ля" - выбор и "b-си" - цикл с выходом из середины), а их длительность - глубину вложенности. Музыкальная окраска программы 9 дает позволяет легко устранить ее зацикленность в случае, если, например, в ней вместо знака "<" (меньше) по ошибке проставлен знак "<=" (меньше или равно), а в исходном сортируемом массиве есть два одинаковых числа. В этом случае программа будет звучать как заезженная пластинка. Прервать ее выполнение можно не только аккордом Ctrl-Break, но и легким ударом не по дисплею (см. пример 1), а по системному блоку ЭВМ. Оператор SPEAK в программе 9 подобен оператору PRINT: он служит для вывода информации, но не на дисплей или на принтер, а на динамик машины: элементы массива при этом выговариваются. У оператора SPEAK есть параметры, меняя которые можно заставить машину быть полиглотом и выговаривать переменные на разных языках, разным голосом (мужской женский, детский) и с разной интонацией.

Европейская гамма "до-мажор" (C#, C-дур: тон, тон, полутон, полутон, тон, тон, тон, полутон) с семью звуками основными (до, ре, ми, фа, соль, ля и си) и с пятью вспомогательными (до-диез, ми-бемоль, фа-диез, ля-бемоль и си-бемоль) созвучна другому творению Европы - языку Pascal, у которого семь основных (структурирующих) и пять вспомогательных (деструктурирующих) средства изменения течения алгоритма. Поэтому Pascal-программу можно озвучить так:

- составной оператор - begin... end - "до";

- цикл с предпроверкой - while... do... - "ре";

- цикл с постпроверкой - repeat... until... - "ми";

- цикл с параметром - for... do... - "фа";

- альтернатива - if... then... else... - "соль";

- множественное ветвление - case... of... - "ля";

- вызов процедуры-функции - имя процедуры-функции - "си".

Эта семерка "структурирующих" звуков будет озвучивать программу дифтонгами, отмечая начала и концы соответствующих блоков. А вот бемоли-диезы будут одиночными, отмечая в программе деструктурирующее ключевое слово goto и следующие встроенные функции:

- переход к метке - goto... - "до-диез";

- завершение процедуры - exit - "ми-бемоль";

- остановка программы - halt... - "фа-диез";

- прерывание цикла - break - "ля-бемоль";

- продолжение цикла - continue - "си-бемоль".

А теперь давайте немного помечтаем и представим себе, что операторы языка не только расцвечены (Quick Pascal, Turbo Pascal 7.0, VBWin 2.0, VBWin 3.0) но и озвучены. Если теперь программу запустить в режиме пошагового выполнения, то трассировка программы породит целую цветомузыкальную симфонию под названием "Аудиовизуальная отладка". Звук будет особо полезен при исследовании рекурсивных алгоритмов. Цвет трассировки будет метаться по операторам, заключенным между объявлением процедуры-функции и ее вызовом. Но только меняющаяся длительность дифтонгов будет свидетельствовать о том, что никакого зацикливания нет, а есть путешествие по структуре программы - по ее второму измерению.

Семинотный музыкальный настрой можно отнести не только к языку Pascal, но и ко второму популярному языку программирования - к языку C. А вот Бейсик опирается на иную музыкальную основу, т.к. включает в себя не семь, а пять структурных управляющих конструкций:

- цикл с заранее неизвестным числом повторений - do... loop;

- цикл с заранее известным числом повторений - for... next;

- альтернатива - if... then... else.. end if;

- множественное ветвление - select case... end select;

- вызов процедуры-функции - call(имя процедуры-функции).

Эту закономерность можно объяснить с "музыкальной" точки зрения. Дело в том, что пять нот, а не семь - это основа восточного звукоряда, а не европейского: на Востоке на уроках сольфеджио распевают "аa-ее-ии-оо-уу", а не "до-ре-ми-фа-соль-ля-си" как на Западе. Языки Pascal и C создавались программистами для собственного употребления. Язык же Бейсик задумывался как инструментальное средство для "восточных туземцев" - непрофессиональных программистов, использующих компьютер для решения своих прикладных задач. BASIC - это не только аббревиатура английской фразы "Beginner's All-purpose Symbolic Instructions Code". Слово BASIC имеет и и прямой перевод - основной язык программирования. В колониальные века миссионеры использовали basic english (основной английский), состоящий из примерно 300 слов, для общения с туземцами.

Пример 9

В составе любой среды программирования есть инструменты отладки (debuging, дословный перевод с английского - обезжучивание). Эта калька с английского не такая уж бессмысленная. Один из первых компьютеров стал барахлить из-за того, что в его электронных внутренностях запутался таракан, закоротил контакты, обуглился и, как некий связист-камикадзе, замкнул их, внеся тем самым изменение в электронную схему машины.

Если мастер, ремонтируя телевизор, уронит в его недра детальку (a bug - жучок), то он подстилает под него газетку и трясет над ней телеприемником, пока эта деталька, способная вывести телевизор из строя, не выпадет.

Листинг 9

'Исходный текст программы "Календарь"

'на языке BArSIC (r - Реагирующий)

INPUT "Год,месяц,день"; Year, Month, Day

Month=Month+1

IF Month < 4 THEN Month=Month+12:Year=Year-1

Day=INT(365.25*Year)+INT(30.6001*Month)+Dey

SELECT CASE Day-7*INT(Day/7)

CASE 0:?"Воскресенье

CASE 1:?"Понедельник

CASE 2:?"Вторник

CASE 3:?"Среда

CASE 4:?"Четверг

CASE 5:?"Пятница

CASE ELSE:?"Субота"'случай 6

ENDS ELECT

' Текст программы после удара по левой стенке дисплея

' и потряхивания дисплея с текстом программы

INPUT "Год, месяц, день ";Year, Month, Day

Month = Month + 1 ' Вставлены пробелы

IF Month < 4 THEN ' Разделены служебные слова

            Month = Month + 12

            Year = Year - 1

END IF ' Выделено плечо неполной альтернативы

Day = INT(365.25 * Year) + INT (30.6001 * Month) + Day

SELECT CASE Day - 7 * INT(Day / 7 )

            CASE 0 ' Выделены заголовки случаев

                        PRINT "Воскресенье"

            CASE 1

                        PRINT "Понедельник"

            CASE 2

                        PRINT "Вторник"

            CASE 3

                        PRINT "Среда"

            CASE 4

                        PRINT "Четверг"

            CASE 5

                        PRINT "Пятница"

            CASE 6 ' Ничего другого (ELSE) нет

                        PRINT "Суббота"

END SELECT

NEWSPAPER ' Подстелили газету для сбора ошибок

            Dey (Day) Субота (Суббота)

            ' Ошибка (Исправлено)

END NEWSPAPER

На листинге 9 помещен исходный текст программы определения дня недели по дате с двумя "детальками-жучками" (Субота вместо Суббота и Dey вместо Day), а также ее работоспособный вариант. Барсик программа отлаживается так. Исходный текст программы выводится на дисплей, который затем приподнимается и трясется (я не шучу), пока все ошибки не "выпадут" на газету (буфер NEWSPAPER). Программа легче читается и отлаживается, если ее структурные элементы на листинге выделены пробелами от начала строки. Структурируется листинг программы на Барсике легким ударом по левой стенке дисплея. Удар по правой стенке восстанавливает первоначальный текст, который в ОЗУ машины и на диске занимает меньше места. В среде Барсика для получения контекстной подсказки не нужно переводить курсор на участок программы, где находится интересуемая переменная или функция, а затем нажимать клавишу F1. Достаточно постучать по определенному месту стекла дисплея и спросить: "Кто там?". Глядя на знаки вопросов вместо слов PRINT, отмечая отсутствие замыкающих кавычек в названиях дней недели в верхней части листинга 10, можно вспомнить фразу из романа Д.Гранина "Зубр": "Ученый должен быть достаточно ленив, - объяснял мне Зубр. - На этот счет у англичан есть прекрасное правило: не стоит делать того, что все равно сделают немцы." Так вот - не стоит делать того, что все равно сделает среда программирования Барсик - она сама заменит знак вопроса на слово PRINT, поставит кавычки там, где ничего другого стоять не может, отструктурирует текст программы, исправит ошибки и сделает многое другое.

Как говаривал Даниил Хармс, вот, собственно, и все!

Литература:

1. Очков В. Ф. «Языки программирования GW-BASIC и QBasic: сравнительное описание». М.: Энергоатомиздат, 1992

2. Очков В. Ф. «Visual Basic и формула Вирта» – КомпьютерПресс, №7 и 8, 1994

3. Очков В. Ф. «Двенадцать программ с дублями и эпиграфами, или Три триады программирования, или Третий лишний, а второй неправильный». – Монитор, № 4, 1993

4. Очков В. Ф. «Turbo Pascal 7.0 Взгляд со стороны». – КомпьютерПресс, № 7, 1933

5. Очков В. Ф. «Сказ про то, как Mathcad задачу решал». – КомпьютерПресс, № 1 и 2, 1995