Каковы лучшие практики программирования на Прологе и рекомендации по стилю?

Хорошо, я знаю, что это очень общий вопрос и что по этому вопросу было написано несколько статей, но у меня такое ощущение, что эти публикации охватывают очень базовый материал, и я ищу что-то более продвинутое, что улучшило бы стиль и эффективность. Вот что у меня есть на бумаге:

  • «Отчет об исследовании AI-1989-08 Эффективный пролог: практическое руководство» Майкла А. Ковингтона, 1989 г.
  • «Эффективное программирование на Прологе», Тимо Кнуутила, 1992 г.
  • «Руководство по кодированию для Пролога» Ковингтона, Баньяры, О'Кифа, Вилемакера, Прайса, 2011 г.

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

Что бы вы добавили сюда из своего личного опыта работы с Прологом? Существуют ли какие-либо специальные рекомендации по стилю, применимые только к программированию на CLP? Знаете ли вы о некоторых распространенных проблемах эффективности и знаете, как с ними бороться?

ОБНОВИТЬ:

Некоторые интересные (но все еще слишком общие и слишком общие для меня) моменты приведены здесь: Руководство по программированию на Прологе от Lifeware Team

Просто чтобы осветить всю проблему, я хотел бы процитировать «Руководство по кодированию для Prolog» (Ковингтон и др.):

Насколько нам известно, последовательный и достаточно полный набор руководств по написанию кода для Пролога никогда не публиковался. Более того, когда мы смотрим на корпус опубликованных программ на Прологе, мы не видим появления стандарта де-факто. Наиболее важная причина этого очевидного упущения заключается в том, что небольшое сообщество Пролога из-за отсутствия всеобъемлющего языкового стандарта далее раздроблено на подсообщества, сосредоточенные вокруг отдельных систем Пролога, ни одно из которых не занимает доминирующего положения.


person Grzegorz Adam Kowalski    schedule 25.04.2014    source источник
comment
Обязательная к прочтению книга — «Искусство Пролога» Ричарда О’Кифа.   -  person Paulo Moura    schedule 26.04.2014
comment
Эта цитата взята из опубликованного набора руководств по написанию кода для Пролога…   -  person Daniel Lyons    schedule 26.04.2014
comment
@DanielLyons, я не понимаю, что вы имеете в виду под своим комментарием. Я написал именно откуда взята эта цитата.   -  person Grzegorz Adam Kowalski    schedule 26.04.2014
comment
@GrzegorzAdamKowalski Я думаю, что Дэниел, возможно, указывает на самореферентную иронию цитаты.   -  person lurker    schedule 26.04.2014
comment
Этот вопрос был отложен некоторыми людьми как не по теме, потому что такие вопросы, как правило, привлекают самоуверенные ответы и спам. Ну, это было мое намерение привлечь самоуверенные ответы. Должен ли я перенести этот вопрос на какой-либо другой веб-сайт вопросов и ответов Stack Exchange?   -  person Grzegorz Adam Kowalski    schedule 27.04.2014


Ответы (1)


Для разработки чистых интерфейсов на Прологе я рекомендую прочитать стандарт Пролога, см. изо-пролог.

В частности, конкретный формат кодирования встроенных предикатов, который включает в себя определенный стиль документации, а также способ сигнализации об ошибках. См. 8.1 Формат встроенных определений предикатов стандарта ISO/IEC 13211-1:1995. Вы найдете определения в этом стиле в Интернете в Cor.2 и пролог Пролога.

Очень хорошим примером библиотеки, которая следует правилам сигнализации ошибок ISO до буквы (и при этом не стандартизирована), является реализация library(clpfd) в SICStus и SWI. Хотя обе реализации принципиально различаются по своему подходу, они используют соглашения об ошибках с максимальной выгодой.

Вернемся к ИСО. Это формат ISO для встроенных предикатов:

x.y.z Имя/Местность

В начале может быть короткое факультативное неформальное замечание.

x.y.z.1 Описание

Дается декларативное описание, которое очень часто начинается с самой общей цели, используя описательные имена переменных, чтобы на них можно было ссылаться позже. Если значение предиката вообще не является декларативным, оно либо утверждается «истинно», либо используется какое-либо иное ненужное операционализирующее слово, такое как «унифицирует», «собирает». Позвольте мне привести пример:

8.5.4 копия_термин/2

8.5.4.1 Описание

copy_term(Term_1, Term_2) истинно, если и только если Term_2 объединяется с термином T, который является переименованной копией (7.1.6.2) Term_1.

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

Другой пример: sort/2. Это теперь отношения или нет?

8.4.3 сортировка/2

8.4.3.1 Описание

sort(List, Sorted) истинно, если и только если Sorted объединяется с отсортированным списком List (7.1.6.5).

Так что, опять же, никакого отношения. Удивлен? См. 8.4.3.4 Примеры:

8.4.3.4 Примеры

...

sort([X, 1], [1, 1]).
   Succeeds, unifying X with 1.

sort([1, 1], [1, 1]).
   Fails.

При необходимости добавляется отдельное процедурное описание, начинающееся с «Процедурно,». Это снова не покрывает никаких ошибок вообще. Это одно из больших преимуществ стандартных описаний: все ошибки отделены от «выполнения», что помогает программисту (= пользователю встроенного) более систематически выявлять ошибки. Честно говоря, это немного увеличивает нагрузку на разработчика, который хочет оптимизировать вручную и в каждом конкретном случае. В любом случае такой оптимизированный код часто подвержен незаметным ошибкам.

xyz2 Шаблон и режимы

Здесь дается исчерпывающая одно- или двухстрочная спецификация режимов и типов аргументов. Эта нотация очень похожа на другие нотации, которые берут свое начало в декларациях режима DECsystem-10 1978 года.

8.5.2.2 Шаблон и режимы

arg(+integer, +compound_term, ?term)

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

xyz3 Ошибки

Приведены все состояния ошибок, каждое в своем подпункте, пронумерованном в алфавитном порядке. Кодекс в разделе Ошибки 7.12:

Когда выполняется более одного условия ошибки, ошибка, о которой сообщает процессор Prolog, зависит от реализации.

Это означает, что каждое условие ошибки должно указывать все предварительные условия, где оно применимо. Все они. Условия ошибки не читаются как if-then-elsif-then...

Это также означает, что кодировщик должен приложить дополнительные усилия для нахождения хороших условий ошибки. Все это в интересах фактического программиста-пользователя, но, конечно, немного неудобно для кодировщика и разработчика.

Многие состояния ошибок напрямую следуют из спецификации, приведенной в x.y.z.2, в соответствии с ПРИМЕЧАНИЯМИ в разделе 8.1.3 Ошибки и в соответствии с 7.12.2 Классификация ошибок. (резюме). Для встроенного предиката arg/3 из спецификации следуют ошибки a, b, c, d. Только ошибка е не вытекает.

8.5.2.3 Ошибки

а) N является переменной
instantiation_error.

б) Term является переменной
instantiation_error.

c) N не является ни переменной, ни целым числом
type_error(integer, N).

г) Term не является ни переменной, ни составным термином
type_error(compound, Term).

д) N — целое число меньше нуля
domain_error(not_less_than_zero, N).

x.y.z.4 Примеры

(Необязательный).

x.y.z.5 Самозагружаемые встроенные предикаты

(Необязательный). Определяет другие предикаты, настолько похожие, что их можно «загрузить».

person false    schedule 26.04.2014