Давайте предположим, что мы читаем из стандартного ввода и строим список всех прочитанных строк.В конце нам нужно отобразить эти строки, разделенные запятыми.
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 ).
Проблема с этим кодом состоит в том, что вызов append
в processInput/3
стоит нам O (n).Как мы можем избежать этой стоимости и при этом позволить нашему предикату быть хвостово-рекурсивным (потому что мы можем читать много строк из стандартного ввода)?
Мне пришло в голову, что мы можем заменить append
наследующий.
LinesSoFar1 = [ Line | LinesSoFar ],
И мы могли бы перевернуть список перед его отображением.Но это кажется вздорным.Есть ли лучший способ?