In formulating these layout rules, we have taken certain arbitrary choices between different sensible formatting variants. While these choices work well for us, you may want to adapt a slightly different style. As long as it is done consistently (and agreed within a team), you should follow your own preferences.
B.1 General guidelines
Code should be indented consistently. Tabs should be every 8 spaces.
Indentation should be one tab per level of indentation, except for
highly indented code which may be indented at 4 spaces per level of
indentation after the first.
Each line should not extend beyond 79 characters, unless this is necessary
due to the use of long string literals. If a statement or predicate call
is too long, continue it on the next line indented two levels deeper.
If the statement or call extends over more than two lines, then make sure
the subsequent lines are indented to the same depth as the second line.
Here is A_really_long_statement_that_does_not_fit +
On_one_line + In_fact_it_doesnt_even_fit +
Don't put more than one statement or call on a line.
Put spaces after commas in comma-separated lists. Put spaces either
side of infix operators. In both cases, this makes them easier to read,
particularly in expressions containing long names or names with underscores.
(There are some exceptions, such as module qualification
foo/3. But not unification
X = Y or list consing
[Head | Tail].)
Make judicious use of single blank lines in clause bodies to separate logical
B.2 Predicates and clauses
Keep all clauses of a predicate in the one place. Leave at least one
blank line between the clauses of one predicate and the next (particularly
if they have similar names), since otherwise they may at first glance
appear to be all from the same predicate (of course, this never happens
because there's a comment before every predicate, right?). Similarly,
it is best not to leave blank lines between the clauses of a predicate
(particularly if done inconsistently), since otherwise at first glance
they may appear to be from different predicates.
Clause heads should be flush against the left margin. As well as making
them easier to pick out visually, this makes it easier to grep for the
definitions of predicates (as opposed to their invocations). The head/body
separator `:-' should follow the head on the same line. The body of the
clause should then commence on the next line, indented one tab stop.
non_overlap(Start1, Dur1, Start2, _Dur2):-
Start1 + Dur1 #=< Start2.
non_overlap(Start1, _Dur1, Start2, Dur2):-
Start1 #>= Start2 + Dur2.
If-then-elses should always be parenthesised. Always include the else part, even if you don't think
it's required. Always put semicolons at the start of a new line, aligned
with the opening and closing parentheses. Example:
( test1 ->
Disjunctions should be formatted in a similar way. Example:
B.5 Do loops
Do loops should also always be parenthesised. Loop conditions should be
listed one per line, starting after the opening parenthesis
and indented one character. The `do' keyword should be at the end of the last condition. The body of the
loop should then follow on the next line, again indented. Example:
(for(J, I + 1, N),
param(A, I) do
Diff is J - I,
A[I] #\= A[J],
A[I] #\= A[J] + Diff,
A[I] #\= A[J] - Diff
Every predicate should have a one line comment documenting what it does,
all module interfaces should be properly documented with a comment directive.
If an individual clause is long, it should be broken into sections, and
each section should have a block comment describing what it does; blank
lines should be used to show the separation into sections. Comments should
precede the code to which they apply, rather than following it.
% This is a block comment; it applies to the code in the next
% section (up to the next blank line).
If a particular line or two needs explanation, a line comment
% This is a "line" comment;
% it applies to the next line or two
% of code
or an inline comment
blahblah % This is an "inline" comment
should be used.