Каковы лучшие практики программирования Prolog и рекомендации по стилю?
Хорошо, я знаю, что это очень общий вопрос и было написано несколько статей по этому вопросу, но у меня есть ощущение, что эти публикации охватывают очень простой материал, и я ищу что-то более продвинутое, что улучшило бы стиль и эффективность. Вот что я имею в статье:
- "Отчет об исследовании AI-1989-08" Эффективный пролог: практическое руководство "", Майкл А. Ковингтон, 1989
- "Эффективное прологическое программирование" Тимо Кнуутила, 1992
- "Руководство по кодированию для Пролога", Ковингтон, Баннара, О'Киф, Wielemaker, Цена, 2011
Примеры предметов, охватываемых этими: хвостовая рекурсия и дифференциальные списки, правильное использование индексации, правильное использование сокращений, избегание утверждений и отказов, избегание CONSing, рекомендации по форматированию кода (отступы, if-then-elses и т. Д.), Соглашения об именах, документирование кода, порядок рассуждений, тестирование.
Что бы вы добавили сюда из своего личного опыта с Прологом? Существуют ли какие-либо особые рекомендации по стилю, применимые только к программированию CLP? Знаете ли вы о некоторых общих проблем эффективности и знаете, как их решать?
ОБНОВИТЬ:
Здесь приводятся некоторые интересные (но все же слишком общие и слишком общие для меня) замечания: рекомендации по программированию на прологе группы Lifeware
Просто, чтобы подчеркнуть всю проблему, я хотел бы процитировать "Рекомендации по кодированию для Пролога" (Covington et al.):
Насколько нам известно, последовательный и достаточно полный набор руководств по кодированию для Prolog никогда не был опубликован. Более того, когда мы смотрим на корпус опубликованных программ Prolog, мы не видим появления фактического стандарта. Самая важная причина этого очевидного упущения заключается в том, что небольшое сообщество Прологов из-за отсутствия всеобъемлющего языкового стандарта далее фрагментировано на суб-сообщества, сосредоточенные вокруг отдельных систем Пролог, ни одна из которых не занимает доминирующее положение.
1 ответ
Для проектирования чистых интерфейсов в Prolog, я рекомендую прочитать стандарт Prolog, см. Iso-prolog.
В частности, конкретный формат кодирования встроенных предикатов, который включает в себя определенный стиль документации, а также способ сообщения об ошибках. См. 8.1 Формат определений встроенных предикатов ISO/IEC 13211-1:1995. Вы найдете определения в этом стиле онлайн в Cor.2 и прологе Пролога.
Очень хорошим примером библиотеки, которая следует буквенным соглашениям об ошибках ISO (и пока не стандартизирована), является реализация library(clpfd)
в SICStus и SWI. Хотя обе реализации принципиально различаются по своему подходу, они используют соглашения об ошибках в своих лучших интересах.
Вернуться к ISO. Это формат ISO для встроенных предикатов:
xyz Имя / Арити
В начале может быть короткое необязательное неофициальное замечание.
xyz1 Описание
Дается декларативное описание, которое очень часто начинается с самой общей цели с использованием описательных имен переменных, чтобы к ним можно было обращаться позже. Если значение предиката вообще не является декларативным, то оно либо указывается как "верно", либо используется какое-либо иное ненужное операционализирующее слово, например "унифицирует", "собирает". Позвольте мне привести пример:
8.5.4 copy_term / 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 и руководством Covington et al., Которое носит неформальный характер и устанавливает, как программист должен использовать предикат. Подход ИСО описывает, как будет вести себя встроенный модуль, в частности, какие ошибки следует ожидать. (Существует 4 ошибки, следующие из вышеперечисленных, плюс одна дополнительная ошибка, которую нельзя увидеть из спецификации выше, см. Ниже).
Ошибки xyz3
Все условия ошибки даны, каждый в своем собственном подпункте пронумерован в алфавитном порядке. Кодекс в 7.12 Ошибки:
Когда удовлетворяется более чем одно условие ошибки, ошибка, о которой сообщает процессор Prolog, зависит от реализации.
Это означает, что каждое условие ошибки должно содержать все предварительные условия, к которым оно относится. Все они. Условия ошибки не читаются как if-then-elsif-then...
Это также означает, что кодификатор должен приложить дополнительные усилия для нахождения хороших условий ошибки. Это все в пользу настоящего программиста пользователя, но, безусловно, немного болезненно для кодификатора и разработчика.
Многие условия ошибок непосредственно следуют из спецификации, приведенной в xyz2, в соответствии с ПРИМЕЧАНИЯМИ в 8.1.3 Ошибки и в соответствии с 7.12.2 Классификация ошибок ( резюме). Для встроенного предиката arg/3
, ошибки a, b, c, d следуют из спецификации. Только ошибка е не следует.
8.5.2.3 Ошибки
а)
N
переменная
-instantiation_error
,б)
Term
переменная
-instantiation_error
,с)
N
не является ни переменной, ни целым числом
-type_error(integer, N)
,г)
Term
не является ни переменным, ни составным термином
-type_error(compound, Term)
,е)
N
целое число меньше нуля
-domain_error(not_less_than_zero, N)
,
Примеры xyz4
(Необязательный).
Встроенные предикаты начальной загрузки xyz5
(Необязательный). Определяет другие предикаты, которые настолько похожи, что они могут быть "загружены".