Что означает символ "-" в Прологе при работе со списками?

Я читал ответ на этот вопрос,

p(X) :- read(A), q(A,X-[]).

q(end,X-X) :- !.    
q(A,[A|X]-Y) :- read(B), q(B,X-Y).

Приведенный выше код использует синтаксис List-List. Я немного понимаю, что происходит, но я хочу знать, что именно здесь делает символ / предикат "-". Кроме того, это специфический SWI?

2 ответа

Решение

(-)/2 представлять списки различий - довольно необычное соглашение. В старых книгах другой оператор (\)/2 тоже был использован.

Многие предпочитают использовать два отдельных аргумента вместо этого. Есть несколько преимуществ по сравнению с использованием оператора:

  1. Предикат не может быть случайно использован с неустановленной переменной для аргумента. Думать о звонке q(A, X) на месте q(A, X-[]),

  2. Выполнение даже немного более эффективно при использовании двух аргументов. Многие системы, такие как SWI, должны создавать каждую (-)/2 структура динамически.

Тем не менее, есть и другой способ использования списков различий, который часто менее подвержен ошибкам: для этой цели вы можете использовать dcg.

На самом деле в программе есть две ошибки, одна из которых связана с обработкой списка различий. Другая ошибка заключается в том, что программа не обрабатывает конец файла. Было бы лучше использовать end_of_file на месте end, Но это поверхностная вещь, которую вы бы нашли рано или поздно.

Другая, более тонкая ошибка связана с взаимодействием между списками различий и сокращением. Я не большой поклонник сокращений, но давайте посмотрим на это правило. Срез режет после того, как все на его левой стороне было выполнено.

q(end_of_file,X-X) :- !.

Первым аргументом является атом end_of_file, Так как мы используем q/2 только с результатом read/1 в качестве первого аргумента, это может быть только сравнение. Итак, мы находимся в конце файла (или потока). Затем, однако, есть и другие вещи, которые должны быть выполнены. И только в том случае, если это удастся, будет выполнено сокращение: Второй аргумент должен быть (-)/2 (ок, во всех местах есть минус на своем месте). А потом: два аргумента (-)/2 должны быть одинаковыми (должны объединяться). Зачем? Мы находимся в конце файла, но если эти аргументы не объединяются, будет применено другое правило.

Когда это происходит? Вот такой неприятный случай:

p([X,Y,Z]).

И просто введите одну константу, скажем, my_constant. и затем нажмите Cntrl-d или Cntrl + z. Что должно p/1 делать в таком случае? В идеале, это может произойти сбой после завершения ввода. Тем не менее, он будет ждать дальнейшего ввода.

Причина в неправильном размещении среза. Мы говорим, что p/1 не стойкий Это распространенная ошибка в программах Prolog. Я могу только рекомендовать сократить использование сокращений и принятие DCG. С DCG этого не может быть:

p2(X) :- read(A), phrase(q2(A),X).

q2(end_of_file) --> !.
q2(A) --> [A], {read(B)}, q2(B).

В DCG срез выполняется независимо от аргумента p/1,

Я думал, что вы имели в виду:.

Это список различий.

http://en.wikibooks.org/wiki/Prolog/Difference_Lists

Другие вопросы по тегам