Обзоры
Самый летний… язык программирования
0

Самый летний… язык программирования

Вспоминая те времена, когда термины "компьютер"
и "пользователь" были, мягко говоря, несовместимыми, можно прийти к
парадоксальным выводам. Громоздкие и представляемые в прессе ужасно неудобными
мэйнфреймы одновременно притягивали и отталкивали.

В этом мире новичку ждать серьезной помощи было неоткуда. "Население околомэйнфреймового
мира" не страдало ксенофобией, но жило по своим собственным законам. Мэйнфреймы,
как это ни странно, не формировали сегодняшней степени зависимости своего мирка
от себя. Они создавали некий аналог социальной иерархии, но в этой иерархии работали
совсем другие законы. Если программа была нужна — ее писали, если готовой программой
можно было воспользоваться — ее учили.

С тех времен слишком многое изменилось, ушли в прошлое и сложнейшие операционные
системы, и многие технологические средства, но кое-что все-таки осталось. Предмет
нашего обсуждения — язык REXX — на сегодняшний день "пережил" и целое
семейство ОС, в котором он родился, и семейство ОС, в котором продолжил развитие
уже в мире ПК. По-своему уникальный язык-долгожитель REXX по-прежнему развивается
и активно используется, он дал жизнь еще двум разработкам, ему посвящено море
ресурсов в Internet и множество книг. И как бы в продолжение (и в качестве дополнительного
доказательства) прозвучавшего в предыдущей статье утверждения о жизнеспособности
и необходимости "средних сереньких" проектов, REXX — разработка, о
которой говорить в исключительной форме трудно. Это самый заурядный язык, без
ухищрений, утонченности, не основанный ни на уникальных идеях, ни на строгих и
сложных математических построениях. Типичный хороший инструмент, отвечающий главному
критерию качества инструмента — его использованию легко обучиться, а получаемая
выгода с лихвой компенсирует затраты на изучение, REXX отлично характеризуется
несколько необычным названием статьи. Действительно, в летнюю жару, когда борьба
между желанием поваляться на берегу моря и стремлением к эффективному использованию
своего "свободного" времени достигает пика, REXX дает очень удобный
выход из положения. На изучение этого языка уйдет буквально несколько дней, а
достигнутый эффект превзойдет все ожидания. Тем более что сегодняшние реализации
классического REXX доступны практически для всех платформ "за бесплатно".

Факты и история

По воспоминаниям Майка Колишоу,
автора языка REXX, первоначальное название его было Rex, и возникло просто
потому, что… звучание этого слова нравилось ему самому

Начнем с самого важного сведения. REXX — язык интерпретируемый,
попадающий в обширную категорию скриптовых языков. Но, в отличие от большинства
разработок, REXX — одновременно и язык стандартный (стандарт ANSI X3.274).
При детальном ознакомлении с историей скриптинга такая особенность уже кажется
интересной, даже уникальной. Наличие стандарта, конечно, не может свидетельствовать
о совершенстве той или иной разработки, но с точки зрения программиста, этот
факт исключительно важен — так как стандарты изменяются редко, то и реализации
стандартов также нечасто существенно изменяют функциональность. Соответственно,
инвестиции времени и сил разработчика в изучение стандартного технологического
продукта более эффективны — ведь в этом случае знания и умения остаются в цене
достаточно долго и позволяют высвободить время (и получить дополнительные средства)
на совершенствование куда более важных профессиональных качеств (например, алгоритмической
подготовки). История REXX начиналась во времена абсолютно уникальной и самой
удачной ОС своего времени — VM/370. Виртуальная машина VM/370 позволяла использовать
мэйнфреймы в качестве эквивалента множества персональных компьютеров, предоставляющих
относительную свободу "пользователям" в выборе "персональной"
ОС. В перечне последних особое место занимала весьма популярная система CMS
(Conversational Monitor System, система управления диалогом) — интерактивная
однопользовательская ОС, унаследовавшая многие хорошие черты знаменитой предшественницы
(или точнее, прародительницы) Unix ОС Multics. Одна из главных черт — командный
характер диалога "человек-машина", наследованная CMS от Multics, в
этой ОС была доведена если не до совершенства, то, по крайней мере, до одной
из лучших реализаций. Командный язык CMS и сегодня остается одним из самых "очеловеченных"
языков подобного назначения — с очень простым и легко понимаемым синтаксисом
и чистой семантикой. В дополнение к командному языку, ориентированному на интерактивное
управление (ввод-реакция системы), CMS располагала и языком управления заданиями,
называемым EXEC. Во многом напоминавший аналогичный язык из более знакомого
сегодня ПК-мира MS/PC/DR DOS, EXEC был мощнее и менее удобнен. Его наследник
— EXEC 2, появившийся в середине 70-х, — обладал всеми признаками настоящего
скриптового языка, но, по мнению многих специалистов IBM, оставался слишком
неудобным — написанный на ассемблере интерпретатор, хоть и славился надежностью
и качеством кода, серьезно ограничивал возможности разработчиков. Так, EXEC
2 требовал явного указания пользователем/программистом назначения того или иного
слова в тексте программы — ключевые слова языка и имена переменных необходимо
было предварять специальным символом (впрочем, многие даже очень популярные
скриптовые языки по сей день в той или иной степени "страдают" подобной
болезнью, когда удобство и простота реализации интерпретатора доминируют над
удобством использования языка).

Все предпосылки появления нового инструмента возникли, и результаты не заставили
себя ждать. За дело взялся сотрудник IBM Майк Колишоу (Mike Cowlishaw). Первая
версия языка появилась во внутренней сети IBM в 1979 г. и моментально снискала
популярность. По воспоминаниям самого автора языка, первоначальное название
его было Rex, и возникло просто потому, что… звучание этого слова нравилось
самому Колишоу. Впрочем, отличия REXX от Rex на этом не заканчиваются — первые
версии были далеки от сегодняшнего воплощения языка. С 1983 г. REXX стал неотъемлемой
частью ОС VM, в 1985 г. появилась его реализация для PC DOS, с 1987 по 1989
— расширенный REXX приходит в OS/2 и AS/400. Начиная с версии OS/2 2.1.3 REXX
становится самым мощным скриптовым языком в этой системе, максимально приближая
ее к возможностям ОС Unix. Последний фактор сыграл и злую шутку — начинающие
пользователи "нового поколения" восприняли приближение к возможностям
рабочей станции как "отдаление от персонального компьютера". И без
того непростое положение OS/2 обострилось разрывом между недавними партнерами
— Microsoft и IBM. В начале 90-х годов лишенная поддержки Microsoft в области
разработки пользовательского интерфейса IBM производит обмен лицензиями со знаменитой
Commodore — компьютеры Amiga начинают оснащаться REXX в качестве скриптового
языка, а OS/2 заимствует элементы GUI Amiga. В это же время REXX "прорывается"
на традиционно трудную для освоения "еще одним скриптовым языком"
территорию Unix — пока только AIX производства самой IBM. В 1996 г. завершается
принятие стандарта ANSI X3.274, и сторонние реализации REXX для всевозможных
платформ начинают расти как грибы после дождя.

Сегодня очень трудно сказать, как сложится и судьба OS/2, попавшей в руки новых
хозяев, что будет с так много обещающим обновлением проекта Amiga, мэйнфреймы
класса IBM 370 превращаются в музейные экспонаты или металлолом, а REXX остается
живым и развивающимся языком и технологическим средством. Достаточно поискать
в Internet ресурсы, связанные с REXX, чтобы убедиться — язык жив и с каждым
днем приобретает пусть не тысячи, пусть десятки, но убежденных приверженцев.

Скажи компьютеру "скажи"

Прежде чем "погрузиться" в знакомство с REXX, совсем не лишним будет
привести пусть не в дословном переводе, но с максимальной точностью сохраняя
смысл, один очень важный фрагмент текста ANSI стандарта X3.274:

"Язык REXX создавался для достижения четырех главных целей:

  • легкой понимаемости (читаемости) написанных на нем программ,
    что облегчает работу программистам, пользователям и сопровождающему персоналу;
  • поддержки быстрого, эффективного и аккуратного программирования
    за счет обеспечения максимально естественной формы представления данных и
    управляющих структур языка;
  • обеспечения надежной и эффективной реализации языка на
    разнообразных платформах;
  • высокой применимости языка в системном и прикладном ПО".

Вот теперь пришло время знакомиться с REXX поближе. В отличие
от многих скриптовых языков с динамической типизацией, в которых тип является
свойством данных (значений), а переменные представляют собой контейнеры, способные
хранить значения любого типа, REXX предусматривает один-единственный тип —
строку символов. В этом плане у REXX есть "близнец" — знаменитый
язык Tcl (Tool command language), которому уже была посвящена одна из статей
автора. Соответственно, общим у REXX и Tcl является и подход к трактовке значений
данных — в этих языках семантика значений определяется характером их использования.
Несмотря на кажущуюся ограниченность такой модели, значения в REXX ни в коей
мере не ограничивают возможности программиста, следует только уточнить предыдущее
определение: "строки символов" в REXX, во-первых, динамически изменяют
свой размер, во-вторых, их максимальная длина ограничивается только возможностями
платформы и доступным объемом памяти (для современных компьютеров — виртуальной).

Реализация стандартного REXX гарантирует автоматическую инициализацию всех переменных
при их первом использовании, при этом выполняется правило "бережного отношения
к ресурсам" — если переменной не присваивалось значение, она не инициализируется.
Если содержимое переменной можно трактовать как запись числа в строковом виде
(вне зависимости от количества пробелов до и после числа), такое значение можно
использовать в арифметических операциях без всяких дополнительных языковых конструкций.
Особый интерес представляют вопросы точности арифметических способностей REXX
и гибкости управления точностью.

Вот, наконец, вполне работоспособный пример:

000 say "Время запуска задачи"time()
001 Factor = ZFACTOR(" 1004 ")
002 say "Количество цифр ="LENGTH(Factor)
003 say "Первые двадцать цифр ="LEFT(Factor,20)
004 say "Время запуска задачи" time()
005 exit
006 ZFACTOR: procedure
007 N = ARG(1)
008 numeric digits 4000
009
010 Zfact = 1
011 do II=2 to N
012 Zfact = Zfact * II
013 end
014 return Zfact

Это простенькая программка, вычисляющая значение факториала.
Впрочем, не такая уж простенькая — она включает в себя собственно вычислительную
подпрограмму ZFACTOR и примитивный, но нужный пользовательский интерфейс. Если
запустить ее на выполнение с помощью практически любого REXX-интерпретатора,
результат будет таким:

Время запуска задачи 13:37:16

Количество цифр = 2580

Первые двадцать цифр = 40642523636098770765

Время окончания задачи 13:37:17

Предварительно давайте обратим внимание на точность полученного результата (2580
цифр — это впечатляет) и на строку 008 листинга, в которой почти человеческим
языком интерпретатору REXX мы указали максимальную точность представления чисел
— 4000 символов! И при этом на вычисления было затрачено менее 1 с (для "высококлассного"
компьютера автора — Intel Pentium 200 MHz).

Теперь пора рассмотреть нюансы приведенного примера. Во-первых, отметим примечательную
особенность — в теле нашей "программы" нигде не использовались никакие
дополнительные конструкции, указывающие интерпретатору на то, что мы хотим работать
(и работаем) с числами. Определение этого факта — забота самого интерпретатора.
Больше того, мы умышленно "поиздевались" над программой, указав в
строке 001, где вызывается процедура ZFACTOR, в качестве параметра не совсем
число. Точнее, строку, способную породить массу эмоциональных сообщений от интерпретаторов
самых разных языков, — ведь строка " 1004 " начинается с двух пробелов
и заканчивается двумя пробелами! В случае с REXX — это не помеха, забота отделения
"зерен от плевел" переложена с программиста на сам интерпретатор.
Факт этот хоть и кажется малозначительным, но на деле существенно облегчает
жизнь непрограммирующему программисту, предпочитающему концентрироваться больше
на решении задачи, чем на изучении и постоянном контроле за использованием особенностей
технологических средств.

Во-вторых, обратим внимание на игриво-детский синтаксис. Вместо замысловатых
аббревиатур, которыми "обзываются" в разных языках команды вывода,
в REXX все предельно просто. Просто скажи компьютеру "скажи" (say,
строки 002 и 003) и укажи, что сказать, — все остальное, опять же, забота интерпретатора.
Но за почти шутливой формой скрывается очень важный и тонкий нюанс REXX — в
этом языке базовые средства ввода/вывода реализованы полноценными встроенными
командами, а не в виде внешних, платформенно-зависимых библиотек. В частности,
использованная нами команда say выдает "на печать" (на текущее устройство
вывода) строку, получаемую в результате выполнения некоторого выражения. Это
сведение открывает еще один нюанс REXX — в выражениях с командой say (000,
002, 003, 004) также не понадобились какие-либо дополнительные конструкции.
Мы просто перечислили то, что нужно "напечатать", все остальное —
опять же забота REXX. К "игривости" синтаксиса следует отнести и примитивное
описание процедуры (функции) — фактически это метка со спецификатором procedure
(006), и примитивную форму представления циклического оператора (011—013),
и, наконец, полное отсутствие каких-либо специальных символов в программе. Короче
говоря, за детской простотой скрывается тщательная продуманность всех языковых
конструкций. К последним, специфическим именно для REXX, можно отнести представленный
в строке 007 образец типичного маленького "швейцарского ножика" —
вызов встроенной функции ARG для получения параметров, переданных в процедуру.
Без всякого изменения синтаксиса ARG может использоваться в нескольких формах,
например для получения количества переданных аргументов вызывается ARG без параметров
(ARG()), для получения значения аргумента с номером N (ARG(N), что и использовано
в примере), для проверки факта существования аргумента с номером N (ARG(N,’Exist’)).

Пора от игрушечных (но исключительно удобных) особенностей REXX перейти к вещам
куда более серьезным. Правда, от характера синтаксического изящества и здесь
избавиться не получится. Например, блестящая реализация команды INTERPRET, трактующей
параметр как (что очевидно из названия) текст исполняемой программы на REXX,
не требует никаких дополнительных сведений для ее использования. Действительно,
достаточно вспомнить, что в REXX все — это строки, взглянуть в справочник по
языку за подсказкой о форме представления строк и уже можно написать: INTERPRET
‘say "Привет"’

Интерпретатор, как и ожидалось, честно "напечатает" "Привет".
Пример, конечно, элементарный, но врожденная способность REXX к исполнению автоматически
сгенерированных программ — вещь замечательная. Как и на удивление изящная реализация
композитных типов данных в REXX, также не требующая дополнительных сложных разъяснений.
Здесь надо только запомнить два момента:

  1. основа всех композитных типов в REXX — ассоциативные
    массивы;
  2. форма доступа к элементам композитных типов REXX аналогична
    форме, например URL ("адреса" в Internet).

Страшно? На деле все значительно проще, больше того — элементарно.
Достаточно написать, например, так:

X.1 = "Двигатель"
X.2 = "Кузов"
X.3 = "Трансмиссия"
do K=1 to 3
say X.K
end

В результате получилось, что в переменной X хранится аналог
обычного массива строк. Но здесь же можно добавить еще одну переменную, демонстрирующую
"реверсивную" способность REXX, например такую:

Y."Двигатель" = 1
Y."Кузов" = 2
Y."Трансмиссия" =3

А вот это уже вовсе не массив в привычном понимании, ведь
в качестве индекса в нем используются строки. Если же добавить к такой возможности
опять же врожденную "многомерность" REXX — ведь количество индексирующих
значений может быть фактически произвольным, то возможности внешне столь примитивного
механизма уже не кажутся игрушечными. Судите сами:

Z.0.0.0.0 = 6000
Z."One"."Two"."Three" = 7000


Это уже и многомерный массив, и высокоуровневый аналог примитивной структуры,
который при разумном применении, например, команды INTERPRET можно легко и красиво
превратить в аналог класса (по крайней мере, в весьма близком к REXX Tcl такие
возможности используются вовсю).

Классические свойства скриптовых языков — ориентированность на обработку строк,
приспособленность к расширению функциональности одновременно и приложений (за
счет встраивания интерпретатора), и языка (за счет встраивания приложений в
интерпретатор) в REXX присутствуют в полном объеме, и касаться их мы даже не
будем. Тем более что на их изучение много времени и сил не потребуется, а не
слишком благодарную задачу, которую традиционно ставит перед собой автор ("не
изменять направление взглядов, сколь легко это ни было бы, а перемещать предметы
так, чтобы они попадали в поле зрения"), можно считать выполненной.

Где и что

Интерпретаторов REXX существует множество. Большинство из них более чем мобильны,
и прекрасно работают в самой разной операционной среде. Хорошие сборники ресурсов,
посвященных REXX, можно найти на сайтах dmoz.org/Computers/Programming/Languages/Rexx/,
www2.hursley.ibm.
com/rexx/
.


Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: