Some ideas on how to present our PEG examples

This is a links version of the example page: contains the examples with links to execution in several Prologs.

An example:

Consider the factorial example, using Peano arithmetic, that we saw in the first part of the course:

factorial(0,s(0)).
factorial(s(N),F) :-
    factorial(N,F1),
    times(s(N),F1,F).

This version is very attractive:

  • It is fully reversible!
  • But also inefficient…

However, we can also code it using ISO-Prolog arithmetic, i.e., is/2:

 ... Z is X * Y ... 

Note that this type of arithmetic has limitations: it only works in
one direction, i.e., X and Y must be bound to
arithmetic terms.

But it provides a (large!) performance gain. Also, meta-logical tests
(see later) allow using it in more modes.

The factorial program can be encoded using is/2 as follows:

SWI :gear: Ciao :gear: XSB :gear: … (i.e., here we would put links to run in different Prologs,
maybe with slightly different code)

:- module(_,_). 

factorial(0,1). 
factorial(N,F) :-
    N > 0,
    N1 is N-1,
    factorial(N1,F1),
    F is F1*N.

% Try it:
% ?- factorial(20,F).
%
% Now it works even for very large numbers: 
% ?- factorial(100,F).
%
% But it does not run "backwards":
%
% ?- factorial(N,40320).

Note that wrong goal order can raise an error (e.g., moving the last
call to is/2 before the call to factorial). We can solve this using constraints:

SWI :gear: Ciao :gear: XSB :gear:

:- module(_,_).
:- use_package(clpq).

factorial(0,1). 
factorial(N,F) :-
    N .>. 0,
    N1 .=. N-1,
    factorial(N1,F1),
    F .=. F1*N.

% And now it runs in both directions, and more efficiently than Peano: 
% 
% ?- factorial(8,F).
% 
% ?- factorial(N,40320).