LaurVas

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

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

  1. Кому это нужно?
  2. А где это используется?
  3. Что мне понадобится?
  4. Забавный пример
  5. Ссылки

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

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

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

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

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

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

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

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

UPD: Пока переписывал статью на markdown, захотел поискать пакеты в Debian, Arch, Gentoo

$ pacman -Ss prolog
community/gprolog 1.4.4-1
    GNU Prolog
community/python-pyswip 0.2.3-1
    Python wrapper for SWI-Prolog
community/python2-pyswip 0.2.3-2
    Python wrapper for SWI-Prolog
community/swi-prolog 7.2.2-1
    Prolog environment

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

Насколько мне известно, самым популярным интерпретатором является 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.