#swi-prolog
#пролог
Вопрос:
Я запускаю некоторое правило Prolog, которое использует функцию вычитания, и в трассировке стека я обнаружил, что источником ошибки является это:
lists:subtract([b, d | _], [b, d] , [r]) ? creep
ERROR: Out of local stack
Исходный вызов был:
member(b, X), member(d, X), subtract(X, [b, d], [r]).
и ожидаемый результат [b, d, r]
.
Я новичок в Prolog и не могу понять источник ошибки и как ее исправить. Пожалуйста, помогите.
Ответ №1:
невозможно понять источник ошибки и как ее исправить.
Просто возьмите свой запрос и посмотрите только на первые две цели:
?- member(b, X), member(d, X).
X = [b,d|_A]
; X = [b,_A,d|_B]
; X = [b,_A,_B,d|_C]
; X = [b,_A,_B,_C,d|_D]
; X = [b,_A,_B,_C,_D,d|_E]
; ... .
Только эти две цели дают уже бесконечно много ответов. Поэтому, что бы ни последовало, ваш запрос никогда не завершится. Случайно вы можете получить решение, но чаще всего вы попадаете в какой-то цикл.
Итак, прежде всего, вам нужно как-то это исправить.
Затем рассмотрим значение subtract/3
в SWI:
?- subtract([b,d,r], [b,d], [r]).
true.
?- subtract([b,d,X], [b,d], [r]).
false. % ?? why not X = r?
Из одного этого вы можете видеть, что subtract/3
это не отношение. Таким образом, вы не можете использовать его как отношение, например, append/3
.
Чтобы исправить это и сохранить как можно ближе к исходному запросу, используйте library(reif)
и library(lambda)
:
?- S1=[b,d,X], S2 = [b,d], tpartition(S2 E^memberd_t(E,S2),S1,_,[r]).
S1 = [b,d,r], X = r, S2 = [b,d].
Ответ №2:
library(lists)
Содержит ряд старых предикатов для управления наборами, представленными в виде неупорядоченных списков, в частностиintersection/3
,union/3
,subset/2
иsubtract/3
. Все эти предикаты используютсяmemberchk/2
для поиска эквивалентных элементов. В результате это нелогично, а объединение может легко привести к сомнительным результатам.
У вас возникла эта проблема, потому что subtract не является чистым и требует создания первых двух аргументов, следовательно
, знак в его документации.
subtract( Set, Delete, -Result)
вместо этого вы можете использовать union / 3
union( Set1, Set2, -Set3)
вы можете узнать больше о других индикаторах режима здесь.