Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Стили и методы программирования. Учебное пособие для СПО
.pdf
Язык Рефал был создан В. Ф. Турчиным для аналитических вычислений
в физике. Первоначально Турчин продумал саму идею конкретизации и
представил ее в виде языка, демонстративно записанного в не слишком
прямо представимой форме. Например, не было понятия
детерминатива, предложения имели вид, подобный
§1.1.2 E1 + (E2 * E3)= (K E1 + E2 .)* (K E1 + E3
.)
Конкретно-синтаксическая форма языка, данная в теоретической работе
Турчина (см., напр. [27
]) сразу же была изменена для удобства
представления и работы
5)
. Уже при первой реализации был продуман и
проверен приведенный выше алгоритм отождествления, были
выброшены иерархические комментарии в начале предложений, а
вместо них появились понятия детерминатива и функции.
Дальнейшая доработка потребовала процедур ввода-вывода и
механизма хранения глобальных данных, что было реализовано через
стеки закопанных данных. Получившийся язык Рефал-2 длительное
время был практическим стандартом Рефал-систем.
В языке Рефал-4 были сделаны две попытки расширения языка. Вопервых, как и во множестве других систем, к Рефалу были достаточно
механически добавлены нарождавшиеся модные объектноориентированные средства. Эта попытка быстро зашла в тупик и была
оставлена. Во-вторых, были определены метаоперации. Это
нововведение доказало свою жизнеспособность и выжило. В языке
Рефал-5 [37
], который сейчас является фактическим стандартом6),
объекты были отброшены, зато последовательно была проведена как
стандартная надстройка над языком идея метакодирования. В нем
получили свое окончательное оформление вложенные процедуры и
дополнительные условия.
Из других существующих версий языка стоит отметить Рефал-6 и Рефал+
[10
], которые развивают одну и ту же линию. В реализации Рефал+
отошли от представления, принятого в [25
], с тем чтобы
воспользоваться современными алгоритмами сборки мусора. Вместо
стеков закопанных значений в этих языках предлагаются объекты,
которые имеют лишь одно значение. В частности, такие объекты
Стили и методы программированияНепейвода Н.Н.
111

используются для описания графического ввода и вывода, что
полностью игнорируется в стандартном Рефале. В этих версиях
позволяется объявить функцию откатной и пытаться при
невозможности отождествлений обработать неудачу. Но автор этих
версий проигнорировал концептуальную несовместимость неудач с
общей структурой управления в языке Рефал. Из находок Рефал+,
помимо новой структуры данных, стоит отметить концепцию
упорядочения возможных отождествлений и возможность до некоторой
степени управлять этим упорядочением (правда, в языке предусмотрен
лишь переход от прямого порядка к его обращению, но уже это дает в
некоторых случаях большой выигрыш в выразительности).
Наиболее заметным недостатком новых версий языка Рефал
7)
явилось
отсутствие различения абстрактного и конкретного синтаксиса. Можно
было бы просто отказаться от фиксации оформления в определении
языка и дать возможность определять синтаксические расширения и
представления самим разработчикам.
Стоит заметить, что нынешний язык Рефал находится в мягком
концептуальном противоречии со столь блестяще реализованной в нем
же идеей динамического вычисления программ. Решение исполнять ту
функциональную скобку, внутри которой нет других таких скобок, было
оправдано и логично при создании Рефала, а теперь оно уже мешает
эффективно использовать аппарат метапреобразований. Необходимо
заметить, что Рефал созрел для настоящего представления
мультииерархической структуры, что позволит языку выйти на новые
классы приложений. Таким образом, в ближайшее время можно
ожидать появления нового сентенциального языка, реализующего идею
конкретизации. Будет просто беда, если под красивой оберткой ктонибудь подсунет в эту область концептуально непродуманное
'прагматическое' решение. Выигрыш от прагматизма будет
минимальным, временным и локальным, а потери — длительными, на
порядок превосходящими аналогичные для традиционных языков, и к
тому же глобальными.
Именно в языке Рефал было четко показано, как выбирать структуры
данных и алгоритм работы абстрактной машины для нетрадиционных
вычислений и насколько это важно. В нем впервые избавились от
жесткой привязки к конкретному синтаксису. Он продемонстрировал
Стили и методы программированияНепейвода Н.Н.
112

советскому программистcкому сообществу возможность альтернативных
моделей вычислений, выполнив на востоке ту же роль, что Prolog на
западе. В нем впервые была реализована концепция встроенных
частичных вычислений программ. Он не поддался давлению моды, и
этим способствовал осознанию наличия альтернатив даже в том случае,
когда подходы в принципе близки. Всего этого достаточно для
признания пионерской роли этого языка.
Сравнение версий сентенциального программирования
Прежде всего, методы управления языка Prolog и языка Рефал
принципиально отличаются. В Prolog'е неудача глобальна, но
исправима, а в Рефале — локальна, но фатальна.
Унификация в Prolog и конкретизация в Рефале являются операциями
примерно одного и того же уровня общности. Но направления
унификации и конкретизации ортогональны.
Конкретизация имеет дело с выражениями, подвыражения в
которых могут выделяться различными способами, и древовидная
иерархическая структура сочетается с линейной структурой
внутри одного уровня иерархии, а при унификации в Prolog и в
логике все выражения жестко ограничены скобками либо
запятыми, то есть присутствует лишь иерархическая структура.
Конкретизация не заглядывает внутрь иерархии глубже, чем это
явно указано в соответствующем правиле, а унификация может
двигаться по уровням иерархии вглубь настолько, насколько это
необходимо.
При конкретизации переменные локальны, и их значения не
влияют на интерпретацию остальной области памяти, а при
унификации переменные глобальны, полученная в результате
унификации подстановка производится сразу во всем поле зрения,
а не только в его активной части.
При конкретизации в ходе установления значений переменных
возможны неудачи и возвраты, а при унификации значения
переменных рекурсивно набираются в соответствии с алгоритмом
нахождения унифицирующей подстановки, и неудача этого
единственного варианта означает неудачу всей попытки
Стили и методы программированияНепейвода Н.Н.
113

унификации.
Внимание!
Модели унификации и конкретизации формально несовместимы,
поскольку, соединив их, мы получаем алгоритмически неразрешимое
понятие отождествления (Н. К. Косовский и др., 1990).
Это — глубочайший теоретический результат и одно из редких прямых
предупреждений, сделанных теорией практике
8)
. Поэтому при сходстве
многих идей, положенных в их основу, эти модели развиваются и
должны дальше развиваться независимо (что не исключает творческого
заимствования идей из одной ипостаси подхода в другую). Обратите
внимание, что мы столкнулись с той же самой ситуацией, которая имеет
место для циклической и рекурсивной ипостасей структурного
программирования.
Точно так же, как циклическая ипостась структурного
программирования, Рефал приспособлен для работы с данными,
развернутыми в основном вширь и для развертывания процесса в
ширину. Точно так же, как рекурсивная ипостась, Prolog приспособлен
для развертывания процесса в глубину и для работы с данными,
имеющими ограниченную ширину, но зато большую глубину.
Даже машинная реализация этих языков сродни двум ипостасям
структурного программирования. В Рефале вызовы, которые выглядят
как рекурсивные, на самом деле рекурсией не являются
9)
, поскольку мы
заканчиваем породивший вызов, и лишь после этого переходим к
отработке порожденных. Prolog больше похож на рекурсию, поскольку
после вызова внутреннего предиката мы можем возвратиться к
внешнему и продолжить попытки его унификации. В Рефале достаточно
общего поля памяти, а в Prolog вынуждены запоминать также
управляющие данные ( точки возврата
10)
).
Стоит заметить, что сентенциальное программирование, и особенно
его разновидность, базирующаяся на модели отождествления-замены,
великолепно сочетается с идеей ассоциативной памяти (см. стр. 31), и
здесь возможен прорыв одновременно на аппаратном и программном
уровнях.
Стили и методы программированияНепейвода Н.Н.
114

Вариант сентенциального программирования, базирующийся на
возвратах и унификации, отлично сочетается с идеей машины потоков
данных. Японцы попытались использовать его в своем проекте ЭВМ
пятого поколения. Провал данного проекта надолго дискредитировал
направление соединения сентенциального программирования с
потоками данных, но к нему придется вернуться в будущем на другой
технической и, видимо, на гораздо более концептуально выверенной
программистской основе.
Концепция унификации и возвратов после неудач исключительно
хорошо подходит для выражения -параллелизма (см. § 15.2). Более
того, уже имеются системы (в частности, Muse), реализующие этот
вариант параллелизма в языке Prolog.
Рефал, в свою очередь, великолепно подходит для &-параллелизма.
Подстановки значений переменных в результирующее выражение
можно осуществлять независимо друг от друга. Более того, в принципе
можно было бы даже в нынешнем варианте Рефала вычислять
различные функциональные скобки в параллель, помешать этому могут
лишь значения, передаваемые через аппарат закапываниявыкапывания. Но это — стандартная проблема синхронизации для
параллельных вычислений, с которой можно справляться хорошо
разработанными средствами, тем более что аппарат для
соответствующей разметки программы еще в ходе ее составления
концептуально подготовлен в языке.
Таким образом, две ветви сентенциального программирования
ориентированы даже на разные классы параллельных вычислений.
Именно на примере сентенциального программирования нами был
сделан вывод о том, что и для других стилей должны быть
альтернативные реализации. Их выявлению мешал прежде всего закон
экологической ниши.
При создании и развитии языков PROLOG и Рефал ярко проявились
сильные и слабые стороны русской и англо-американской школ науки.
В. Ф. Турчин проделал адекватный анализ, не устаревший за 40 лет, но
он не стремился к общепонятности и слишком большой популяризации
(может быть, потому, что ему не нужно было выбивать гранты). Его
последователи четко восприняли идею и развивали ее, практически
Стили и методы программированияНепейвода Н.Н.
115

полностью избегая концептуально противоречащих ей возможностей.
Но популяризация языка и внешняя сторона работы с ним (удобные
системы, интерфейсы и т. п.) оказались практически полностью
проигнорированными, и поэтому язык остается достоянием узкой
группы приверженцев.
Сами представители Рефал-сообщества объясняли свою позицию
относительно интерфейсов примерно следующим образом.
— Чайники и ламеры все равно Рефалом не пользуются, а
квалифицированный человек сам легко напишет переходник, тем более,
что код системы открыт.
Автор в свое время вынужден был писать переходник между Рефалом-2
и Алголом 68, но, конечно же, такое решение и приведенная выше
аргументация неудовлетворительны.
Создатели Prolog с самого начала в значительной мере использовали
теорию и методологию как заклинания либо молитвы, не имеющие
отношения к сути дела и произносимые для его освящения. Тем самым
теоретическая база сразу же оказалась неадекватной, что и привело к
быстрому расползанию системы и потере концептуального единства.
Язык в значительно большей мере, чем Рефал, оказался загрязнен
чужеродными элементами
11)
.
Неадекватность теории практике помешала осознанию реальных
достижений подхода, основанного на унификации, поскольку они часто
противоречили мифам и саморекламе. Зато развитие внешнего
оформления и удобных (с точки зрения дизайна) средств работы с
языком шло адекватными темпами, а реклама его действительных и
мнимых достижений далеко опережающими. Язык вошел в практику
обучения многих университетов мира и попал даже в стандарты
программ обучения специалистов IFAC.
Если говорить о практических задачах, то Prolog значительно лучше
подходит для поиска, а Рефал — для синтаксических преобразований.
Стоит также помнить, что в нынешнем состоянии Prolog не может
служить даже для прототипирования, это язык лишь для моделирования
решений и логики поведения программы.Но это — особенность
нынешних конкретных реализаций идеи унификации и возвратов, она
Стили и методы программированияНепейвода Н.Н.
116

связана с тем, что примитивный концептуальный механизм пришел в
противоречие с выявившимися богатейшими потенциальными
возможностями подхода.
Рефал делает символьные преобразования столь же эффективно, как и
программа на традиционном языке, и поэтому может быть использован
на всех уровнях: и для создания прототипа программы, и для написания
надпрограммы, и для написания подпрограммы.
Таким образом, Рефал по эффективности и ясности представления уже
сейчас может служить языком прототипирования, и, если бы его
снабдить удовлетворительными интерфейсами, вполне мог бы служить
и для окончательных решений, работающих в многоязыковой среде. В
момент написания книги существует единственный имеющийся
надежно работающий интерфейс Рефала: с языком PHP преобразования
HTML-текстов.
В особенности Рефал хорош в тех случаях, когда нужно произвести
нетривиальное преобразование символьных входных либо выходных
файлов. Его использование, как показала практика автора и студентов в
многоязыковом программировании, зачастую оправдывается даже
тогда, когда ведется передача данных через файл.
У Prolog ныне интерфейсы имеются, но они, как правило,
ориентированы лишь на C++ и LISP
12)
и совершенно не
стандартизованы. Каждая реализация имеет свой интерфейс.
Мы затронули общий недостаток нынешних систем сентенциального
программирования. Это — плохая проработка связей с другими
языками. При создании средств высших уровней необходимо с самого
начала продумать вопросы связи с другими языками и использования
языка в многоязыковой и многостилевой методологии
программирования.
1)
Они не имели никаких сведений о Рефале и работали совершенно
независимо. Просто потребность сентенциального программирования
назрела. К счастью для информатики, обе группы инициаторов не были
осведомлены о работах друг друга, иначе, скорее всего, одна из двух
ортогональных концепций осталась бы неразвитой. Это подтверждает
история других стилей: тот, кто первым добился успеха, захватывает
Стили и методы программированияНепейвода Н.Н.
117

экологическую нишу и видоизменяет условия в ней таким образом,
чтобы ничто другое не могло в ней выжить (причем часто нет никакого
злого умысла, просто работают законы развития науки и вообще
эволюционирующих систем).
2)
Как именно это делается, сейчас неважно.
3)
Одновременно данное направление нанесло и существенный вред
этой теории и методологии, который был бы еще глубже, если бы у
Prolog'а с самого начала не было бы друга-соперника Рефала.
4)
Слишком прямое применение теории, особенно когда получается
привлекательное на вид следствие — бич современной науки. Именно
оно приводит к тому, что многие серьезные практики попросту
игнорируют теорию, из-за этого делают другие, не менее глупые и
вредные, и не менее привлекательные на вид, ошибки. Пример такой
глобальной ошибки — С++, лишь обостривший все проблемы
традиционного программирования. Он создавался практиками, по их
же собственному признанию, принципиально игнорировавшими
теории.
5)
Если человек не привязан к конкретным словам, то обычно это
доказывает, что он ясно осознал идеи, которые отстаивает.
6)
Внимание! В самых последних реализациях, называемых PZ SciTE,
язык без огласки чуть-чуть пересмотрен, и отражено это лишь в файлах
news.txt.
7)
Подавляющее большинство систем программирования имеют этот
недостаток, но в данном случае он ощущается наиболее остро.
8)
Даже прямые предупреждения, как правило, игнорируются
практиками, многие из которых не понимают самого понятия
алгоритмической неразрешимости; в качестве примера можно взять
безвременно скончавшийся Рефал-6.
9)
Примером того, насколько многие привыкли судить о явлениях по
внешнему виду, а не по сущности, является кочующее из книги в книгу
утверждение о том, что Рефал — язык функционального рекурсивного
программирования.
10)
После этой аналогии становится более ясно, почему программисты
трактуют использование отсечения ! в языке PROLOG как хакерство.
Представьте себе, что было бы, если бы Вам в C++ предоставили явный
доступ к отложенным из-за рекурсии вызовам процедур и разрешили по
своему произволу их убирать!
11)
История отказа от введения объектов в Рефал является практически
Стили и методы программированияНепейвода Н.Н.
118

исключительным в мире современной информатики примером
понимания вреда концептуальных противоречий. В конце концов, разум
должен стоять выше моды!
12)
Некоторые коммерческие системы Prolog имеют интерфейсы еще и с
Java.
Стили и методы программированияНепейвода Н.Н.
119

Функциональное программирование
Теоретические предпосылки. Списки и простейшие операции. Значения
и модель вычислений. Динамическое порождение программ и
функционалы. Объекты и синтез программ.
Функциональное программирование объясняется на примере диалекта
Common Lisp языка LISP. Этот диалект наиболее распространен и имеет
официальный стандарт. Common Lisp может работать не только в
пакетном режиме (когда он запускается как обычная программа), но и в
режиме диалога.
LISP — вероятно, первый из практически реализованных языков
1)
,
который основывался на серьезном теоретическом фундаменте и
пытался поднять практику программирования до уровня концепций, а
не наоборот — опустить концепции до уровня существовавшей на
момент создания языка практики.
В настоящий момент функциональное программирование представлено
целым семейством языков, но LISP свои позиции не сдает.
Лямбда-абстракции
В некоторых случаях осознанное усвоение концепций даже на самом
низком уровне нереально без базовых теоретических сведений. А
знакомство с таким базисом, в свою очередь, стимулирует значительно
более глубокий интерес к теории и способствует пониманию того, что
на высшие уровни знаний и умений не подняться без овладения
теорией.
Теоретической основой языка LISP является логика функциональности:
комбинаторная логика или (по наименованию одного из основных
понятий в наиболее популярной из нынешних ее формализаций) исчисление.
В -исчислении выразительные средства, на первый взгляд, крайне
скупы. Имеются две базисные операции: применение функции к
аргументу (fx) и квантор образования функции по выражению
Стили и методы программированияНепейвода Н.Н.
120
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
