:- module(_,_).

% Dynamic predicates
% ------------------

% A) New, dynamically created predicates are directly modifiable: 

% Try (asking for more solutions):
% ?- p(X). 
% ?- assert(p(a)).
% ?- p(X).
% ?- assert(p(b)).
% ?- p(X).
% ?- retract(p(a)).
% ?- retract(p(b)).
% ?- p(X).
% ?- abolish(p/1).
% ?- p(X).

% B) If the predicate is already defined in the program: 
related(3,4).
% it must be declared dynamic for it to be modifiable: 
:-  dynamic related/2.

% Some operations on related/2: 
relate_numbers(X,Y) :- assert(related(X,Y)).
unrelate_numbers(X,Y) :- retract(related(X,Y)).

% Try:
% ?- related(3, 4).
% ?- related(1, 2).
% ?- relate_numbers(1, 2).
% ?- related(1, 2).
% ?- related(X, Y).
% ?- unrelate_numbers(1, 2).
% ?- related(1, 2).
% ?- abolish(related/2).
% ?- related(1,2).

% B) A definition of append that we can add or delete dynamically: 
:- dynamic app/3.

% Create the definition of append
define_app :-
    assert(   app([], X, X) ),
    assert( ( app([X|Y], Z, [X|W]) :- app(Y,Z,W) ) ).

% Erase the definition of append
erase_app :- 
    abolish(app/3).

% Try:
% ?- app([1,2],[3,4],Y).
% ?- erase_app.
% ?- app([1,2],[3,4],Y).
% ?- define_app.
% ?- app([1,2],[3,4],Y).
% ?- app(X,Y,[1,2,3,4]).
% ?- erase_app.
% ?- app(X,Y,[1,2,3,4]).
