Is there convention for naming intermediate variables?

I found it is a bit hard to name intermediate variables in Prolog.

For example,

in Scheme, we could use nested expressions

(define (fib n)
  (cond
    ((= n 0) 0)
    ((= n 1) 1)
    (else (+ (fib (- n 1)) (fib (- n 2))))))

in Prolog, we have to unnest them

fib(0, 0) :- !.
fib(1, 1) :- !.
fib(N, OUT) :-
        N > 1,
        N1 is N-1,
        N2 is N-2,
        fib(N1, F1),
        fib(N2, F2),
        OUT is F1+F2.

The unnesting makes naming intermediate variables a bit hard. Apparently, N1 ,N2, F1, F2 are not very good names (not readable IMO).

My question is that

Is there any convention for naming intermediate variables? e.g. N1 N2

Another workaround is looking for a special symbol mechanism.

For example,

Scheme r7rs has |...| symbol notation, so we could write:

(define (fib n)
  (cond
    ((= n 0) 0)
    ((= n 1) 1)
    (else
     (let* ((|n-1| (- n 1))
            (|n-2| (- n 2))
            (|fib_n-1| (fib |n-1|))
            (|fib_n-2| (fib |n-2|)))
       (+ |fib_n-1| |fib_n-2|)))))

Thanks.

Various options are floating around. One option is to use DCGs or EDCGs to hide these variables. I’ve also seen notations that represent a pair N0,N1 as a single argument that is macro-expanded into a pair. This requires the pair to be consecutive arguments to predicates and (thus) won’t help here. For the pure Prolog way, one needs some conventions. I typically call them X0, X1, … X if a predicate makes X go through a number of state transitions. A good example is when X is an assoc and we do several modifications on the assoc.

I think your fib/2 example is perfectly fine. Maybe the OUT vs F1/F2 is a little confusing and OUT could be name simply F. Prolog remains a bit clumsy for implementing pure functions. Of course we can use one of the many functional notation extensions. Most suffer from corner cases or unpleasant syntax. Prolog is a relational language. This makes it shines for dealing with relations :slight_smile:

1 Like

For the pure Prolog way, one needs some conventions. I typically call them X0, X1, … X if a predicate makes X go through a number of state transitions. A good example is when X is an assoc and we do several modifications on the assoc.

I don’t quite understand this convention. Could you explain it further?

In the fib/2 example, are the N1, N2 and F1, F2 what you called “X go through a number of state transitions” ?

Suppose you build the atom "<Name> how are you", by consecutively adding one word at a time.

The code would be like this:

greet(Name,Greeting) :-
   atom_concat(Name,     ' how', Greeting0),
   atom_concat(Greeting0,' are', Greeting1),
   atom_concat(Greeting1,' you?',Greeting).

Note: In real life you wouldn’t build up the greeting like this, it is just an example to clearly show
you the variable naming convention.

2 Likes

I feel somewhat sympathetic in that the syntax of prolog variables should be allowed to be extended. The |…| syntax sounds nice for me. Boolean variables library(clpb) are only Prolog variables. So, for ZDD library I extended the syntax for readability. Currently in ZDD, Prolog variables and ground atoms are allowed for propositional variables. So far I met no problems. I guess no problems for any prolog terms provided that it is free from reserved logical operators. Internally the zdd library does simple book keeping for this purpose of generating index using assoc. Compared with ZDD’s core task, this book keeping is negligible.

% ?- zdd_sat_count(a -> (b -> a), C).
%@ C = 4.
% ?- zdd_sat_count(A -> (B -> A), C).
%@ C = 4.
% ?- zdd_sat_count(A -> (b -> A), C).
%@ C = 4.
% ?- zdd_sat_count(prop(1) -> (prop(2) -> prop(1)), C).
%@ C = 4.
% ?- zdd_sat_count(p(a) -> (p(b) -> p(a)), C).

% ?- zdd_sat_count(p(A), C).   % Error