Prev Next Up Home Keys Figs Search New

Indention and Style

Appeared in Volume 9/1, February 1996

Keywords: style.


ok@goanna.cs.rmit.edu.au
Richard A. O'Keefe
5th December 1995

S.Tobies writes:
I was wondering whether there are any recommended indention styles for Prolog. Especially for the ; and the -> operator, but for other constructs as well.
Is there a paragraph in a FAQ or a part of a book you can recommend?

Naturally I recommend the style used in "The Craft of Prolog".

The one fundamentally silly thing that you must never ever do is to put ";" at the end of a line, where it can be mistaken for a comma.

head :-
    goal1,
    goal2,
    (   goal31,
        goal32
    ;   goal33,
        goal34
    ),
    (   goal41 ->
        goal42,
        goal43
    ;   goal44 ->
        goal45
    ;/* not goal41, not goal42 */ 
        goal46
    ).

This works well for me. It's essentially the style in "Ada Quality and Style Guide-Lines" adapted to Prolog.


ludemann@expernet26.expernet.com
Peter Ludemann
5th December 1995

I prefer this:

head :-
    goal1,
    goal2,
    (   goal31,
    ->  goal32
    ;   goal33,
        goal34
    ),
    (   goal41
        goal41a,
    ->  goal42,
        goal43
    ;   goal44
    ->  goal45
    ;/* not goal41, 
        (goal41,goal41a), 
        nor goal44 */ goal46
  ).

My reasons:
  1. It takes no more room that R.A. O'Keefe's style.
  2. it looks better with compound conditions (the "if" parts).


idickinson@lf.hp.com
Ian Dickinson
5th December 1995

I would write:

head :-
    goal1,
    goal2,
    goal3,
    goal4.

goal3 :-
    goal31,
    goal32.
goal3 :-
    goal33,
    goal34.

goal4 :-
    ... etc (you get the picture) ...

Peter Ludemann writes:
1. It takes no more room that R. A. O'K's style.

I don't really worry about the size of the source code. That's what the compiler is for :-)

He continues:
2. it looks better with compound conditions (the "if" parts).

I rarely use Prolog's if construction, and I never nest them. Not that I don't use nested if's in other languages, it's just that I have always found Prolog's if syntax confusing.

A disadvantage, of course, is that if goal3, for example, needs to share any bindings with goals 1 through 4, the variables will have to be passed as parameters. In a complex clause, this may lead to a long list of formal parameters. It is also arguably less efficient, since two extra procedure calls are needed. However, I have learnt (the hard way) to get it right first, then if I can show that it's too slow, and I can show that this is the bottleneck, then and only then should it be optimised. In other words, "clarity over efficiency except in emergency"! Richard O'Keefe expresses some of the same sentiments in The Craft of Prolog.

The original poster asked about indentation rules. The structuring of goals in a clause is one aspect of this. The other rule I use relates to how to layout large structures or long lists of parameters. For example:

literaryGoal( _Arg1, _Arg2,
              pome( had( mary ),
                    little( FarmAnimal ) ),
              [and, have( i, a( hunch ) ),
               tookTo( school, oneDay ),
               and, ateItFor( her( lunch ) )
              ]
            ) :-
    lamb( FarmAnimal ).


dowding@ai.sri.com
John Dowding
8th December 1995

While we're discussing style, I think that it is confusing to mix upper and lower case in predicate/term symbols. Since uppercase letters are necessary in variables, I avoid them in in atoms. For example:

literary_goal( _Arg1, _Arg2,
               pome( had( mary ),
                     little( FarmAnimal ) ),
               [and, have( i, a( hunch ) ),
                took_to( school, one_day ),
                and, ate_it_for( her( lunch ) )
               ]
             ) :-
    lamb( FarmAnimal ).

The variables stand out much better this way.

Unless, Of course, if you're one of those people who starts all their variables with '_'.


ulrich@a0.complang.tuwien.ac.at
Ulrich Neumerkel
10th December 1995

Peter Ludemann's indentation style has another advantage: the ->s are easier to locate. Which helps since -> has a similar effect as cut, and should therefore be as visible as possible. Since I tend to look most at the beginning of lines rather than at the ends, I tend to overread a -> at the end of a line.

By the same token:

error(Message) :-
    throw(Message).

or

error(Message) :-
    raise_exception(Message).

or

error(Message) :-
    write(Message),
    halt.

If this is your first large project, I think it is probably better to avoid ( -> ;) unless the condition is:

  1. an arithmetical comparison, such as </2

  2. var/1; and the then- and else- goals describe the same thing but differ only in runtime. Consider grandparent_of/2, ancestor_of/2.

Prev Next Up Home Keys Figs Search New