Пролог: различное поведение между yap и swi-прологом при чтении файла в список
У меня есть следующий тестовый код, пытаясь прочитать файл в список
open('raw250-split1.pl', read, Stream),
read(Stream,train_xs(TrainXs)),
length(TrainXs, MaxTrain).
Я опущу часть вывода, так как файл довольно большой.
Хорошо работает с yap
,
➜ chill git:(master) ✗ yap [18/06/19| 5:48PM]
% Restoring file /usr/lib/Yap/startup.yss
YAP 6.2.2 (x86_64-linux): Sat Sep 17 13:59:03 UTC 2016
?- open('raw250-split1.pl', read, Stream),
read(Stream, train_xs(TrainXs)),
length(TrainXs, MaxTrain).
MaxTrain = 225,
Stream = '$stream'(3),
TrainXs = [[parse([which,rivers,run,through,states,bordering,new,mexico,/],answer(_A,(river(_A),traverse(_A,_B),next_to(_B,_C),const(_C,stateid('new mexico')))))],
<omited output>
,[parse([what,is,the,largest,state,capital,in,population,?],answer(_ST,largest(_SU,(capital(_ST),population(_ST,_SU)))))]]
Но на swi-prolog
будет производить Type error
➜ chill git:(master) ✗ swipl [18/06/19| 7:24PM]
Welcome to SWI-Prolog (threaded, 64 bits, version 7.6.4)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.
For online help and background, visit http://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).
?- open('raw250-split1.pl', read, Stream),
read(Stream, train_xs(TrainXs)),
length(TrainXs, MaxTrain).
ERROR: raw250-split1.pl:4:
Type error: `list' expected, found `parse(which.(rivers.(run.(through.(states.(bordering.(new.(mexico.((/).[])))))))),
<omited output>
,answer(_67604,(state(_67604),next_to(_67604,_67628),const(_67628,stateid(kentucky))))).[].(parse(what.((is).(the.(largest.(state.(capital.(in.(population.((?).[])))))))),answer(_67714,largest(_67720,(capital(_67714),population(_67714,_67720))))).[].[]))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))' (a compound)
In:
[10] throw(error(type_error(list,...),context(...,_67800)))
[7] <user>
Note: some frames are missing due to last-call optimization.
Re-run your program in debug mode (:- debug.) to get more detail.
В чем может быть проблема для ошибки здесь?
файл raw250-split1.pl
можно найти из ftp
URL ниже, если вы хотите попробовать.
Спасибо вам за помощь!
Я пытаюсь перенести более ранний код в SWI-Prolog
, который был написан в SICStus 3 #3: Thu Sep 12 09:54:27 CDT 1996
или ранее Раймондом Дж. Муни ftp://ftp.cs.utexas.edu/pub/mooney/chill/. Все вопросы с этим тегом связаны с этой задачей. Я новичок в прологе, помощь и предложения приветствуются!
2 ответа
raw250-split1.pl
был, по-видимому, написан с использованием канонической записи. Традиционный список функторов ./2
но SWI-Prolog 7.x изменил его на '[|]'/2
для того, чтобы использовать ./2
для других целей. Это приводит к переменной TrainXs
будучи экземпляром read/2
вызов сложного термина, аргумент которого не является списком:
?- open('raw250-split1.pl', read, Stream), read(Stream,train_xs(TrainXs)).
Stream = <stream>(0x7f8975e08e90),
TrainXs = parse(which.(rivers.(run.(through.(states.(bordering.(... . ...)))))), answer(_94, (river(_94), traverse(_94, _100), next_to(_100, _106), const(_106, stateid('new mexico'))))).[].(parse(what.((is).(the.(highest.(point.(... . ...))))), answer(_206, (high_point(_204, _206), const(_204, stateid(montana))))).[].(parse(what.((is).(the.(most.(... . ...)))), answer(_298, largest(_300, (population(_298, _300), state(...), ..., ...)))).[].(parse(through.(which.(states.(... . ...))), answer(_414, (state(_414), const(..., ...), traverse(..., ...)))).[].(parse(what.((is).(... . ...)), answer(_500, longest(_500, river(...)))).[].(parse(how.(... . ...), answer(_566, (..., ...))).[].(parse(... . ..., answer(..., ...)).[].(parse(..., ...).[].(... . ... .(... . ...))))))))).
YAP все еще использует ./2
Функтор для списков, который объясняет, почему он может справиться с этим. Обходной путь для SWI-Prolog - запустить его с --traditional
опция командной строки:
$ swipl --traditional
...
?- open('raw250-split1.pl', read, Stream), read(Stream,train_xs(TrainXs)).
Stream = <stream>(0x7faeb2f77700),
TrainXs = [[parse([which, rivers, run, through, states, bordering|...], answer(_94, (river(_94), traverse(_94, _100), next_to(_100, _106), const(_106, stateid('new mexico')))))], [parse([what, is, the, highest, point|...], answer(_206, (high_point(_204, _206), const(_204, stateid(montana)))))], [parse([what, is, the, most|...], answer(_298, largest(_300, (population(_298, _300), state(...), ..., ...))))], [parse([through, which, states|...], answer(_414, (state(_414), const(..., ...), traverse(..., ...))))], [parse([what, is|...], answer(_500, longest(_500, river(...))))], [parse([how|...], answer(_566, (..., ...)))], [parse([...|...], answer(..., ...))], [parse(..., ...)], [...]|...].
Ошибка типа вы получаете из-за length/2
ожидание списка, когда первый аргумент связан.
В этом файле в качестве последнего символа присутствует тильда, что приводит к тому, что синтаксис является недопустимым, поэтому его следует удалить перед чтением. Я не знаю, почему YAP принимает файл как действительный, должен вызвать ошибку AFAIK.
В SWI-Prolog есть опция чтения списка точек / 2:
dotlists (Bool)
Если true (по умолчанию false), читать.(A,[]) как список, даже если списки внутренне и не построены с использованием точки в качестве функтора. Это в первую очередь предназначено для чтения выходных данных write_canonical/1 из других систем Prolog. Смотрите раздел 5.1. http://www.swi-prolog.org/pldoc/man?predicate=read_term/2
Это дает желаемый результат без изменения режима:
Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.0)
?- read_term(X, [dotlists(true)]).
|: .(a,.(b,.(c,[]))).
X = [a, b, c].