Suppose we read from standard input and create a list of all the lines that have been read. At the end, we should display these lines separated by commas.
go:-
prompt(_, ''),
processInput([ ], Lines),
findall(_, (member(L, Lines), write(L), write(',')), _),
nl.
processInput(LinesSoFar, Lines):-
read_line_to_codes(current_input, Codes),
processInput(Codes, LinesSoFar, Lines).
processInput(Codes, LinesSoFar, Lines):-
( Codes \= end_of_file
->
atom_codes(Line, Codes),
append(LinesSoFar, [ Line ], LinesSoFar1), % <---- append/3 - O(n)
processInput(LinesSoFar1, Lines)
;
Lines = LinesSoFar ).
The problem with this code is that the call appendto processInput/3us is O (n). How can we avoid this cost and allow our predicate to be tail-recursive (because we can read many lines from standard input)?
It occurred to me that we can replace the appendfollowing.
LinesSoFar1 = [ Line | LinesSoFar ],
And we could flip the list before displaying it. But it seems hacked. Is there a better way?
source
share