type list = ^element;
element = record
info : integer;
next = list
end;
function emptylist : list;
begin
emptylist := nil
end;
function is_empty(L:list): boolean;
begin
if L = nil then is_empty := true else is_empty := false
end;
function cons(x:integer, L:list): list;
var aux : list;
begin
new(aux);
aux^.info := x;
aux^.next := L;
cons := aux
end;
function head(L:list): integer;
begin
if L = nil
then head := 0 /* error */
else head := L^.info
end;
function tail(L:list): list;
begin
if L = nil
then tail := nil /* error */
else begin
tail := L^.next;
dispose(L)
end
end;
A correct use of the ADT should use only the operations of the interface, i.e. emptylist, isempty, cons, head and tail. For instance, consider below two possible definitions of the append function: The first respect this principle, the second doesn't. Of course, if the language offered a mechanism to protect the ADT, the second could not even be written.
function append(L1,L2:list): list
begin
if is_empty(L1)
then append := L2
else append := cons(head(L1),append(tail(L1),L2))
end;
function append(L1,L2:list): list
begin
if L1 = nil
then append := L2
else append := cons(L1^.info,append(L1^.next, L2))
end;