What are the best Prolog programming practices and style guidelines? [closed]

懵懂的女人 提交于 2019-11-29 01:41:21
false

For designing clean interfaces in Prolog, I recommend reading the Prolog standard, see .

In particular the specific format how built-in predicates are codified which includes a particular style of documentation but also the way how errors are signaled. See 8.1 The format of built-in predicate definitions of ISO/IEC 13211-1:1995. You find definitions in that style online in Cor.2 and the Prolog prologue.

A very good example of a library that follows the ISO error signaling conventions up to the letter (and yet is not standardized) is the implementation of library(clpfd) in SICStus and SWI. While both implementations are fundamentally different in their approach, they use the error conventions to their best advantage.

Back to ISO. This is ISO's format for built-in predicates:

x.y.z Name/Arity

In the beginning, there may be a short optional informal remark.

x.y.z.1 Description

A declarative description is given which starts very often with the most general goal using descriptive variable names such that they can be referred to later on. Should the predicate's meaning be not declarative at all, it is either stated "is true" or some otherwise unnecessary operationalizing word like "unifies", "assembles" is used. Let me give an example:

8.5.4 copy_term/2

8.5.4.1 Description

copy_term(Term_1, Term_2) is true iff Term_2 unifies with a term T which is a renamed copy (7.1.6.2) of Term_1.

So this unifies is a big red warning sign: Don't ever think this predicate is a relation, it can only be understood procedurally. And even more so it (implicitly) states that the definition is steadfast in the second argument.

Another example: sort/2. Is this now a relation or not?

8.4.3 sort/2

8.4.3.1 Description

sort(List, Sorted) is true iff Sorted unifies with the sorted list of List (7.1.6.5).

So, again, no relation. Surprised? Look at 8.4.3.4 Examples:

8.4.3.4 Examples

...

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

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

If necessary, a separate procedural description is added, starting with "Procedurally,". It again does not cover any errors at all. This is one of the big advantages of the standard descriptions: Errors are all separated from "doing", which helps a programmer (= user of the built-in) catching errors more systematically. To be fair, it slightly increases the burden of the implementor who wants to optimize by hand and on a case-to-case basis. Such optimized code is often prone to subtle errors anyway.

x.y.z.2 Template and modes

Here, a comprehensive, one or two line specification of the arguments' modes and types is given. The notation is very similar to other notations which finds its origin in the 1978 DECsystem-10 mode declarations.

8.5.2.2 Template and modes

arg(+integer, +compound_term, ?term)

There is, however, a big difference between ISO's approach and Covington et al.'s guideline which is of informal nature only and states how a programmer should use a predicate. ISO's approach describes how the built-in will behave - in particular which errors should be expected. (There are 4 errors following from above plus one extra error that cannot be seen from above spec, see below).

x.y.z.3 Errors

All error conditions are given, each in its own subclause numbered alphabetically. The codex in 7.12 Errors:

When more than one error condition is satisfied, the error that is reported by the Prolog processor is implementation dependent.

That means, that each error condition must state all preconditions where it applies. All of them. The error conditions are not read like an if-then-elsif-then...

It also means that the codifier has to put extra effort for finding good error conditions. This is all to the advantage of the actual user-programmer but certainly a bit of a pain for the codifier and implementor.

Many error conditions directly follow from the spec given in x.y.z.2 according to the NOTES in 8.1.3 Errors and according to 7.12.2 Error classification (summary). For the built-in predicate arg/3, errors a, b, c, d follow from the spec. Only error e does not follow.

8.5.2.3 Errors

a) N is a variable
instantiation_error.

b) Term is a variable
instantiation_error.

c) N is neither a variable nor an integer
type_error(integer, N).

d) Term is neither a variable nor a compound term
type_error(compound, Term).

e) N is an integer less than zero
domain_error(not_less_than_zero, N).

x.y.z.4 Examples

(Optional).

x.y.z.5 Bootstrapped built-in predicates

(Optional). Defines other predicates that are so similar, they can be "bootstrapped".

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!