2014-02-03 1 views
5

Недавно попал в Прологе Я использую его на несколько простых задач и начал задаваться вопросом об использовании элемента в пределах FORALL петель, как в тривиальном примере ниже:Будет ли использовать элемент в рамках предложения forall в SWI-Prolog всегда выводить элементы в том же порядке?

forall(member(A,[1,2,3,4]), print(A)). 

В случае, что вы делаете что-то вроде этого всегда верно, что forall будет обрабатывать элементы в списке в том же порядке каждый раз при его вызове? Есть ли у него должно быть исполнено путем говорят делать что-то вроде:

A = [1,2,3,4], sort(A, B), forall(member(C,B), print(C)). 

от того, что мало исследований я изначально сделал я предполагаю, что это сводится к поведению члена/2, но в документации функции на Сайт SWI-Prolog очень краток. Однако он упоминает детерминизм в отношении члена/2, который дал мне понять, что я могу быть на правильном пути, говоря, что он всегда будет извлекать элементы в том же порядке, хотя я далеко не уверен.

Может ли кто-нибудь дать мне какие-либо гарантии или пояснения по этому вопросу?

+1

Я думаю, что вы можете положиться на него, потому что списки Пролога являются односвязными и любым другим обход будет работать хуже.Я, конечно, не вижу различий в семантике от наименования списка. –

ответ

4

недетерминизм в Прологе просто относится к предикату, имеющим потенциально более одного решения. Очевидно, member/2 является таким предикатом. Это не означает, что вы должны беспокоиться о том, что ваши вычисления становятся непредсказуемыми. В Prolog есть четко определенное правило вычисления, в котором, по сути, говорится, что альтернативные решения исследуются с помощью принципа глубины, слева направо. Таким образом, ваша цель member(X,[1,2,3,4]) будет генерировать решения для X в ожидаемом порядке 1,2,3,4.

Сортировка списка [1,2,3,4] не будет иметь никакого значения, поскольку она уже отсортирована (согласно стандартному порядку заказа Prolog).

Предупреждение о forall/2: некоторые Прологи определяют это, но, вероятно, это менее полезно, чем вы себе представляете, потому что это не «петля». Вы можете использовать его в своем примере, потому что вы выполняете только эффект печати на каждой итерации. Для большинства других целей, вы должны ознакомиться с рекурсивными моделями как

print_list([]). 
print_list([X|Xs]) :- print(X), print_list(Xs). 
+0

+1 приятный, возможно, это скорее то, что у OP было в уме – false

+0

Спасибо @jschimpf, это имеет больше смысла. Также спасибо за советы по рекурсии, это был скорее вопрос о теории того, что происходит при использовании forall, но я знаю, что рекурсия - лучшая идея в целом. –

-1

Строго говоря, нет никакой гарантии в SWI на нескольких уровнях:

1MO, что member/2 или forall/2 будет выполнять именно таким образом, так как вы можете переопределить их.

?- [user]. 
member(X,X). 
|: % user://1 compiled 0.00 sec, 2 clauses 
true. 

?- forall(member(A,[1,2,3,4]), print(A)). 
[1,2,3,4] 
true. 

Однако member/2 определяется в Prolog prologue, которая охватывает все детали вы заинтересованы. Что касается forall(A,B) безопаснее писать \+ (A, \+B) вместо этого, так как это зависит от только стандартных функций. Не существует определения forall/2 как такового, поэтому трудно сказать, что такое «правильное» поведение.

2do, этот SWI будет стандартным. Если вы прочтете документацию, вы заметите, что для стандартного соответствия нет самообъявления (как, например, SICStus Prolog). На самом деле, \+ (A, \+B) не полностью конформным, как показано в следующем примере, который должен молча терпят неудачу, а печатает nonconforming

?- \+ (C= !, \+ (C,fail;writeq(nonconforming))). 
+0

'forall/2' определяется как встроенный предикат в B-Prolog, BinProlog, CxProlog, GNU Prolog, JIProlog, Lean Prolog, LPA WinProlog/MacProlog, Qu-Prolog, SWI-Prolog, XSB, YAP. Он также был указан в предложении проекта пересмотра ИСО Prolog Core от октября 2009 года. Он был проголосован за включение в стандарт на совещании WG17 2009 года. Похоже, что он был отброшен спустя некоторое время. Но это не исключает того, что считается де-факто стандартным предикатом. –

+0

@PauloMoura: за исключением GNU Prolog, ни один из ваших списков не объявляет себя как ISO, который оставляет открытым то, что может означать определение forall/2. Например. YAP: 'forall ((fail, 2), true)' успешно, вместо создания ошибки. – false

+0

Только верхний уровень на YAP. Сопоставьте один и тот же вызов в теле предиката, определенном в файле, и получите ошибку времени компиляции. Крайние случаи, подобные этому, для большинства сценариев использования, не являются проблемой. –

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