Конец потока обнаруживается только тогда, когда вы действительно достигли его. Когда вы читаете последний факт, маркер конца файла еще предстоит прочитать. Попробуйте вместо этого что-то вроде:
memo_to_list(MemoList):-
open('/home/ale/Downloads/Prolog_exercises/memo.dat',read,Stream),
read(Stream,Term),
read_list_from_stream(Term,Stream,MemoList),
close(Stream).
read_list_from_stream(end_of_file,_,[]) :-
!.
read_list_from_stream(memo(Cognome,Ora),Stream,[(Cognome,Ora)|RestoAppuntamenti]):-
read(Stream,Term),
read_list_from_stream(Term,Stream,RestoAppuntamenti).
Вы также можете избежать утечек ручек потоков и незакрытых потоков в случае, если что-то не так с вашим файлом данных, используя встроенный предикат setup_call_cleanup/3
:
memo_to_list(MemoList) :-
setup_call_cleanup(
open('/Users/pmoura/Desktop/memo.dat',read,Stream),
( read(Stream,Term),
read_list_from_stream(Term,Stream,MemoList)
),
close(Stream)
).
Обновление
Стандарт Пролог требует, чтобы за .
, заканчивающим термин, следовал символ макета. Ваш код работает только в том случае, если после последней точки последнего термина нет символа (кроме конца файла), что делает текст Prolog несоответствующим, но, в зависимости от системы Prolog, может разрешать конец потока, который будет обнаружен путем вызова предиката at_end_of_stream /1
после чтения последнего члена. Обратите внимание также, что текстовые редакторы обычно добавляют новую строку после последней строки текста, если ее нет при сохранении. Эта новая строка является символом макета, как того требует стандарт Prolog. Поэтому для совместимого, надежного и переносимого решения убедитесь, что в конце файла данных есть новая строка, и используйте решение в этом ответе.