General
Material
Lecture 1
 Slides Practical Session
Lecture 2
 Slides Practical Session
Lecture 3
 Slides Practical Session
Lecture 4
 Slides Practical Session
Lecture 5
 Slides Practical Session

# Solution

```%% Wrapper: calls the 3-place predicate with the accumulator argument
%% being instantiated to the empty list.
my_flatten(In,Out) :-
my_flatten(In,[],Out).

%% When the list is empty, the accumulator contains the final result.
my_flatten([],Acc,Acc).

%% If the list is non-empty, flatten the tail of the list. The output
%% is TOut. Then use TOut to instantiate the accumulator when
%% flattening the head of the list.
my_flatten([H|T],Acc,Out) :-
my_flatten(T,Acc,TOut),
my_flatten(H,TOut,Out).

%% A special clause to deal with cases where my_flatten is called with
%% a non-list as first argument. This can happen because the previous
%% rule calls my_flatten for the head of its input list and this head
%% is not necessarily a list. In this case, the term is simply added
%% to the front of the accumulator.
my_flatten(X,Acc,[X|Acc]) :-
X \= [],
X \= [_|_].
```