2014-01-21 5 views
5

Этот вопрос относится к материалу, в главе 3 книги: программирования в Прологе, Clocksin и Меллиша, Ed 5структура (Разностные Списки) Пролог

В странице 72 этой книги, разница список программ, используя это отображается:

partsOf(X,P):- partsacc(X,P,Hole) , Hole=[]. 

partsacc(X,[X|Hole],Hole):-basicpart(X). 
partsacc(X,P,Hole):- assembly(X,Subparts), partsacclist(Subparts, P, Hole). 

partsacclist([],Hole,Hole). 
partsacclist([P|T], Total, Hole):- partsacc(P,Total,Hole1), partsacclist(T,Hole1,Hole). 

Во многих обучающих онлайн, следующий формат с помощью "-" используется, например ::

append([ A , B , C | R1 ] – R1 , [ D , E | R2 ] – R2 , R3) 

Мои вопросы:

  1. В чем разница между этими двумя представлениями (с помощью - и она не используется)

  2. В каких ситуациях лучше использовать каждый из них?

Благодаря

+0

Благодарим вас за полезные комментарии. – user17302

ответ

6

Обязательно: Не используйте (-)/2 или (\)/2 или любой другой оператор для представления «списков различий». Причина в том, что у вас часто будет предикат с одним аргументом списка и внутренним предикатом, который использует список различий. Поскольку оба имеют одну и ту же сущность и, вероятно, одно и то же имя, все будет запутывать. Хуже того, это может работать для «некоторых случаев». Кроме того, этот оператор повлечет за собой некоторую стоимость, которую можно избежать с помощью двух отдельных аргументов.

Постарайтесь придерживаться четкого соглашения об именах.То есть S0, S1 ... S. Таким образом, аргументы, представляющие список различий, будут легко видны. Чтобы лучше подчеркнуть, что эти аргументы принадлежат друг другу, некоторые люди не используют пробел после разделительной запятой, тогда как они используют его для других аргументов. Таким образом:

p(L+R, S0,S) :- 
    p(L, S0,S1), 
    p(R, S1,S). 

Кроме того, (-)/2 имеет другое значение в Прологе. Он используется для представления пары Key-Value, как в keysort/2.

Любая книга Пролога, которую я знаю, предлагая оператора для списков разностей, приходит с 1980-х годов.

+0

@Will: Есть [аутентичные ответы] (https://www.quora.com/profile/Alan-Kay-11), сейчас! – false

+0

интересно, спасибо. –

6

Мой опыт в Прологе ограничен, но, кажется, что старые тексты, как правило, используют либо - или другой символ (например \) для обозначения списка и его хвост. Новый код Prolog всегда использует два аргумента (как в первом примере). Например, все встроенные и библиотечные предикаты в SWI-Prolog последовательно используют два отдельных аргумента.

В теории нет разницы в том, какой стиль вы предпочитаете. Я думаю, это не помешает быть последовательным в этом в вашем собственном коде.

На практике разница заключается в том, что вместо составного термина, содержащего два списка в одном аргументе, у вас есть два аргумента, которые должны быть более эффективным представлением.

EDIT

Убедитесь также прочитать ответ на @false.

6

Я согласен с тем, что сказал Борис (+1) относительно разных представлений. Более того, это, на мой взгляд, явно случай, когда вы явно используете DCG, а не кодировку различий в списке. Рассмотрим, например, следующую версию кода:

parts(X) --> { basicpart(X) }, [X]. 
parts(X) --> { assembly(X, Parts) }, assembly_(Parts). 

assembly_([])  --> []. 
assembly_([X|Xs]) --> parts(X), assembly_(Xs). 

Использование, после определения assembly/2 и basicpart/1 точно так, как в вашем примере:

?- phrase(parts(X), Ls).

DCG имеет четкую декларативный и легко читать интерпретации , и требует меньше аргументов.

Смежные вопросы