Страницы

29 нояб. 2012 г.

Все, что я знаю о языке Пролог

Это самый необычный язык, с которым мне когда-либо приходилось сталкиваться. Существует мнение, что тексты программ на Прологе ближе к человеческому мышлению, нежели исходные тексты императивных языков (C, Pascal и др.). Не верьте этому. Пролог является скорее головоломкой, чем языком программирования, а процесс написания программ очень похож на разгадывание кубика-рубика.


Пролог — язык для фанатов рекурсии и головоломок. Циклов в нем не существует, но это не спасает от зацикливания (пример с дверями ниже). Если императивные языки описывают алгоритм, который можно с тем же успехом описать блок-схемой или псевдокодом, то здесь такое представление программы не прокатит. Программисту надо написать такой набор логических рассуждений (как правило рекурсивных, а то слишком просто), который при обработке интерпретатором превращается в алгоритм. Это одновременно баг и фича языка. Компьютеры созданы для выполнения алгоритмов. Пролог хочет обмануть компьютеры.
Знакомство с этим языком я советую начать со статьи на хабрахабре. Нет, правда, отличная статья!

Говорят, что писать программы на Прологе намного сложнее, чем читать их. Увы, это не шутка.

Кому это нужно?

Вам нравится рекурсия. Нет, вы обожаете рекурсию. Нет, вы просто преданы рекурсии и видеть не хотите циклы. Тогда Пролог — это ваш язык. В действительности, 90% осваивающих Пролог делают это, потому что изучают искусственный интеллект в ВУЗе. На мой взгляд, Пролог может быть добровольно интересен программистам, которые хотят в свободное время изучить что-нибудь новенькое и необычное. Но я бы посоветовал не спешить, ведь есть более заманчивые языки: Haskel, Python или Ассемблер. Да и вообще, не стоит забывать, что в жизни есть не только программирование :)

Студентам, которых заставляют изучать этот язык, я сочувствую. Писать программы сложно. Классика жанра — конкатенация двух списков, всего две строчки кода. Признаюсь, я не смог самостоятельно реализовать это за три часа. С другой стороны, когда долго над чем-то сидишь и наконец-то оно заработало… хочется улыбаться.

Пролог интересен прежде всего тем, что он очень необычный. Думай рекурсивно, забудь про циклы!

А где это используется?

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

Что мне понадобится?

Насколько мне известно, самым популярным интерпретатором является SWI-Prolog. Еще встречаются GNU Prolog и Visual Prolog. Для установки под Windows идем на сайт проекта. Под линуксом достаточно установить пакет swi-prolog.

Писать программы можно в любом редакторе. Хорошо, если он поддерживает подсветку синтаксиса этого языка: Kate, Gedit, Medit, наверняка Vim и Emacs.

Изначально редакторы определяют язык как Perl из-за расширения .pl.

С чего начать изучение?

См. ссылки в конце.

Забавный пример

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

/* описываем конфигурацию лабиринта: */ door(1, 2). %существует дверь из первой во вторую комнаты door(2, 3). %из второй в третью и т. д. door(3, 4). /* … */ door(1, 4). door(X, Y):-door(Y, X). %если есть дверь из Y в X, то есть дверь из X в Y

Поначалу код работает так, как от него ожидается:

?- door(2, 3). true ?- door(3, 2). true

Но если спросить у интерпретатора о существовании прохода, которого на самом деле нет…

?- door(99, 100).

…то он ничего не сможет ответить, потому что войдет в ступор зациклится. Чтобы понять, почему так происходит, вводим команду

trace.

Она поможет отследить, что же на самом деле делает интерпретатор и почему он такой дурак. Очень помогает при написании программ, берите на заметку.

[trace] ?- door(99, 100). Call: (6) door(99, 100) ? creep Call: (7) door(100, 99) ? creep Call: (8) door(99, 100) ? creep Call: (9) door(100, 99) ? creep Call: (10) door(99, 100) ?

Почему так получается? Не находя ответа в базе фактов, интерпретатор переходит к предикату door(X, Y):-door(Y, X). и пытается его удовлетворить новым проходом по базе фактов, затем снова цепляется за предикат, и т. д. Бесконечная рекурсия или зацикливание? Правильный ответ — рекурсия, ведь в Прологе нет циклов!

Можете считать меня дураком, но я так и не смог придумать как исправить предикат, чтобы он работал правильно.

Что будет дальше?

Скорее всего, ничего. Напишу ли я еще хотябы строчку на Прологе? Навряд ли.

Ссылки


Кстати, это единственный язык (из тех, что я знаю), в котором есть три разных оператора «равно»: =, =:=, is.
обновлено 06.06.2013

Комментариев нет:

Отправить комментарий