Мой дядя самых честных правил программ исходники за так ...

25 авг. 2009 г.

Пролог: Изучение с нуля

Добрался таки до пролога. Чтобы не потерять, все источники собираю в одном месте.

Реализации:

Редакторы кода:

Источники первичной информации:

       Большая статья из которой можно почерпнуть практически всю доступную информацию о языке Prolog.

        Очень хорошее начало, но, к сожалению, содержит пропуски в некоторых частях, для полноценного изучения не годится.

  • Prolog ISO/IEC 13211-1:1995 - стандарт языка,

       В 1995 году был принят стандарт языка, но к сожалению в свободном доступе его обнаружить не удалось, есть только черновик в PostScript формате.

        Набор документов и программ использованных при разработке стандарта языка.

Туториалы:

Книги:

Задачи:

Другое:

Очень краткое введение

Пролог – это декларативный логический язык программирования. Основными его конструкциями являются логические предложения (например: human('Socrat') :- true.), на основании которых пролог строит некоторые логические выводы. Предложения объединяются в правила с помощью операции and, которая обозначается знаком ','. Предложение при проверке может создавать побочные эффекты, что используется для ввода/вывода.

Краткий путеводитель по синтаксису

% Это строчный комментарий
/* А это блочный комментарий */

goal(X, Y) :-   % goal - это цель, для которой мы собираем правила,
                % имя цели всегда начинается с маленькой буквы.
                % результат у цели - это всегда true или false.
                % X, Y - параметры цели.

    X > Y       % Первое утверждение, которое утверждает что X больше Y.

    ,           % Разделитель между утверждениями, означает логическое И.

    X + 1 == Y  % Второе утверждение, которое может быть верным,
                % только если Y = X + 1.

    .           % Точка означает конец описания цели.

/*
 * Суммирую:
 * Имя цели всегда с маленькой буквы,
 * Параметры цели, и все другие переменные с большой буквы,
 * Утверждения разделяются запятой,
 * Описание цели всегда заканчивается точкой.
 */

prolog('logic language').
% Так записываются некоторые факты,
% и по сути являются сокращениями для цели,
% которая всегда возвращает true.
% в данном случае эквивалент выглядел бы так:
% prolog('logic language') :- true.

% Цели могут быть рекурсивными.
% Посчитаем сумму от 0 до X.
sum(0, 0).   % факт используется для остановки рекурсии.
sum(X, Result) :-
    Y is X - 1,             % is - это по сути присвоение значения.
    sum(Y, SubResult),      % Рекурсивный вызов.
    Result is X + SubResult.


% Цель, которая будет использоваться при запуске программы,
% имя 'main' выбрано мною произвольно.
main :-
    % запрашиваем значение факта
    prolog(Which),
    % выводим значение на экран
    format('prolog is a ~a.', [Which]),

    % newline
    nl,

    % задаём значение X
    X is 100,
    % считаем сумму от 0 до 100
    sum(X, Result),
    % выводим результат с помощью printf-like функции
    format('sum(0, ~a) = ~a.', [X, Result]),

    % newline.
    nl.

/*
 * Вывод программы при запуске:
 * prolog is a logic language.
 * sum(0, 100) = 5050.
 */

Типы данных

Атом: атом или 'атом', начинается с маленькой буквы или обрамляется одинарными кавычками.

Строка: "Строка", обрамляется двойными кавычками, по факту представляет список из чисел – кодов ASCII символов строки.

Число: 10, целые (-1,0,1), плавающая запятая (0.123, 123.456).

Список: [0, 1, 2], набор элементов перечисленных через запятую и обрамлённых квадратными скобками. Элементы могут быть разнородными (разных типов). Списки можно деструктурировать через синтаксис [Head | Tail].

 

Первые результаты

Теперь, с помощью новоприобретённых знаний, можно написать несколько известных примеров:

HelloWorld.pro:

main :- writeln('Hello, Prolog World!'). 

Factorial.pro:

% factorial implementation
factorial(1, 1).
factorial(X, Result) :-
    X > 0,
    X1 is X - 1,
    factorial(X1, Result1),
    Result is X * Result1.
 
main :-
    factorial(7, X),
    writeln(X). 

Fibonachi.pro:

% Fibbonachi sequence implementation
fib(0, 1).
fib(1, 1).
fib(X, Result) :-
    X1 is X - 1,
    X2 is X - 2,
    fib(X1, Result1),
    fib(X2, Result2),
    Result is Result1 + Result2.
 
main :-
    fib(7, X),
    writeln(X). 

QuickSort.pro:

qsort([], []).
qsort([X], [X]).
qsort([Head | Tail], Result) :-
    partition(Head, Tail, Left, Right),
    qsort(Left, LeftSorted),
    qsort(Right, RightSorted),
    append(LeftSorted, [Head | RightSorted], Result).
 
partition(_, [], [], []).
partition(Pivot, [Head | Tail], [Head | Left], Right) :-
    Head =< Pivot,
    partition(Pivot, Tail, Left, Right).
partition(Pivot, [Head | Tail], Left, [Head | Right]) :-
    Head > Pivot,
    partition(Pivot, Tail, Left, Right).
 
append([], Right, Right).
append([Head | Left], Right, [Head | Result]) :-
    append(Left, Right, Result).
 
main :-
    qsort([1, 5, 4, 6, 3, 2], X),
    writeln(X). 

 

Какие ещё есть логические языки программирования?

Путём нехитрых поисков в источниках близким к прологу собрал такой список:

        Расширение языка Haskell для реализации логического программирования.

       Mercury is a new logic/functional programming language, which combines the clarity and expressiveness of declarative programming with advanced static analysis and error detection features.

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

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

9 комментариев:

  1. Спасибо за статью! Может теперь разберусь с прологом)

    ОтветитьУдалить
  2. Здорово для начала)
    Спасибо за обзор!

    ОтветитьУдалить
  3. Бреагромнейшая благодарочка и респект автору!
    Пасибки кароче.

    ОтветитьУдалить
  4. [quote]Задачи:
    99 Prolog problems,[/quote]
    там не тока задачи, но и решения, притом интересные )

    [quote]можно написать несколько известных примеров:[/quote]
    примеры вроде как на SWI. Если так - то append писать не обязательно (там есть встроенный)

    partition, который используется в qsort может быть более функциональным если передавать указатель на предикат, отвечающий за разделение, в качестве аргумента, пример можно глнуть тут: http://pro-prof.com/archives/838

    [quote]Какие ещё есть логические языки программирования?[/quote]
    более толстый список есть в прогопедии, с описанием. Кстати, ссылки в статье у вас инвалидные, на меркури, во всяком случае.

    ссылки "Higher-order logic programming in Prolog" и "99 проблем" точно полезные, я проверил )

    ОтветитьУдалить
  5. Привет всем! У меня вопрос - а где можно найти материалы по написанию минималистичного интерпретатора языка "пролог". Интересна сама внутренняя структура языка. Проекты с "открытым кодом" не предлагать. Открытость кода != простота и понятность, не хочется месяцы искать ответ, что подразумевал автор упомянув "синие занавески"...

    ОтветитьУдалить
  6. Не работают примеры из Братко из раздела Списки. SWI Prolog 7.4.2
    Список2 = (a, .(b, .(c,[]) ) ).
    ERROR: Type error: `dict' expected, found `c' (an atom)
    ERROR: In:
    ERROR: [11] throw(error(type_error(dict,c),_5938))
    ERROR: [9] '$dicts':'.'(c,[],_5978) at e:/programs/swipl/boot/dicts.pl:46
    ERROR: [8] ''(user:(...,...))
    ERROR: [7]
    ERROR:
    ERROR: Note: some frames are missing due to last-call optimization.
    Подскажите, что делать.

    ОтветитьУдалить

Публикуются только комментарии, которые показались автору блога заслуживающими внимания.