:- module(_,_).

% Meta-calls and cut: cut-fail
% ----------------------------

% Fail can be easily programmed in pure logic:
myfail :- a=b.
% Is available simply as 'fail'. 

% We tell the compiler we are redefining the ground/1 built-in:
:- redefining(ground/1).

% Definition of ground/1 using cut and fail:
ground(Term) :- 
    var(Term), 
    !, 
    fail.
ground(Term) :- 
    nonvar(Term), 
    functor(Term,_F,N),
    ground_(N,Term).


ground_(0,_T).       %% All subterms traversed
ground_(N,T) :- 
    N>0, 
    arg(N,T,Arg), 
    ground(Arg), 
    N1 is N-1, 
    ground_(N1,T).

% Try (also in the debugger):
% ?- ground(a).
% ?- ground(X).
% ?- ground(f(a,f(X,d),b)).

% Comment out the first clause of ground/1 and guess what happens.
%
% Try (also in the debugger):
% ?- ground(f(a,f(c,d),Z)).


% ground_(0,T).       %% All subterms traversed
% ground_(N,T) :- 
%     N>0, 
%     ground(~arg(N,T)), 
%     ground_(N-1,T).
