:- module(_,_,[]).

%% Functions can be coded as predicates with one more 
%% argument, which represents the output.

% E.g., the Ackermann function:
% 
% ackermann(0,N) = N+1
% ackermann(M,0) = ackermann(M-1,1)
% ackermann(M,N) = ackermann(M-1,ackermann(M,N-1))
% 
% is represented as plain clauses as follows:

ackermann(0,N,s(N)).
ackermann(s(M),0,Val) :-  
    ackermann(M,s(0),Val).
ackermann(s(M),s(N),Val) :- 
    ackermann(s(M),N,Val1),
    ackermann(M,Val1,Val).

% Try:
% ?- op(100,fy,s).
% (defines s as a prefix operator to save us 
%  writing parenthesis)
% ?- ackermann(s s 0, s s s 0, X).

% But now it also runs 'backwards':
% ?- ackermann(s s 0, s s s 0, s s s s s s s s s 0).
% ?- ackermann(s s 0, Y, s s s s s s s s s 0).
% ?- ackermann(X, s s s 0, s s s s s s s s s 0).
