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

% Database programming

% A) Tables are predicates composed of facts.

% The argnames package allows giving names to arguments.
:- use_package(argnames).

:- argnames
person(   name, age,   sex).
%     ======================
person(  brown, 20,   male).                 
person(  jones, 21, female).	       
person(  smith, 36,   male).   	       

:- argnames
person2(   name, age,   sex).
%      ======================
person2( cabeza, 33,   male).    
person2(  bueno, 39,   male).     
person2(  jones, 21, female).   

:- argnames
lived_in( name,       town, years).
%       ===========================
lived_in( brown,    london,    15).
lived_in( brown,      york,     5).
lived_in( jones,     paris,    21).
lived_in( smith,  brussels,    15).
lived_in( smith, santander,     5).

% B) Operations on tables are predicates composed of rules. 

% Projection:
city(C) :- 
    lived_in(_,C,_).
% Try:
% ?- city(C).

% Alternative definition, using argnames: 
city_(C) :- 
    lived_in${town => C}.

% Try:
% ?- city_(C).

% Union:
all_persons(Name,Age,Sex) :- 
    person(Name,Age,Sex).
all_persons(Name,Age,Sex) :- 
    person2(Name,Age,Sex).
% Try:
% ?- all_persons(Name,Age,Sex).

% Difference (note \+ not pure! But see NaF / Clarks's completion later...)
difference(Name,Age,Sex) :- 
    person(Name,Age,Sex), 
    \+ person2(Name,Age,Sex).
difference(Name,Age,Sex) :- 
    person2(Name,Age,Sex),
    \+ person(Name,Age,Sex).
% Try:
% ?- difference(Name,Age,Sex).

% Cartesian Product:
person_X_lived_in(Name1,Age,Sex,Name2,Town,Years) :- 
    person(Name1,Age,Sex), 
    lived_in(Name2,Town,Years).
% Try:
% ?- person_X_lived_in(Name1,Age,Sex,Name2,Town,Years).

% Selection:
underage_person(Name,Age,Sex) :- 
    person(Name,Age,Sex), 
    Age < 21. % We should use Peano here also of course.
% Try:
% ?- underage_person(Name,Age,Sex).

% Intersection:
person_lived_in(Name,Age,Sex,Town,Years) :-
    person(Name,Age,Sex), 
    lived_in(Name,Town,Years).
% Try:
% ?- person_lived_in(Name,Age,Sex,Town,Years).

% Join:
person_joinName_person2(Name,Age,Sex) :-
    person(Name,Age,Sex), 
    person2(Name,_Age2,_Sex2).

% Try:
% ?- person_joinName_person2(Name,Age,Sex).
