Пролог Лучшая практика: проверка того, что переменная уже связана. - PullRequest
4 голосов
/ 10 июня 2010

Я отправил это решение на вопрос, но ony оставил мне комментарий:

Предикаты, чтобы проверить, является ли "переменная" свободный или уже связанный должен измениться стратегия получения права унификации для других «переменных» (т.е. ускорить или сделать возможным вывести их). То же самое для динамического предикаты - они могут быть использованы для ускорить что-то, но они не должны использоваться как триггер изменения поведение чего-то.

Мне интересно, почему это так. Почему плохой практикой является проверка того, что что-то уже определено для чего-то другого? Как вы думаете, это плохая практика? Существуют ли другие варианты, которые будут «лучшей практикой».

Вот мое решение:

% ================================
% Ensures that all variables are unique.  
% ================================

% Base case: Assigned variables unique values
used([], Nin, Nin).

% Have already assigned a value to this variable
used([A|B], Nin, Nout) :-
        integer(A), % <----------------- THIS IS THE LINE IN QUESTION
        helper(B,Nin,Nout).

% Have not assigned a value to this variable yet
% Assign it and remove it from the list.  
used( [A|B] , Nin, Nout) :-
        member(A,Nin),
        delete(Nin,A,Temp),
        helper(B,Temp,Nout).

1 Ответ

8 голосов
/ 12 июня 2010

Основная проблема таких предикатов, как integer/1, atom/1 и т. Д., Заключается в том, что они не монотонны .

Возьмем, к примеру, ?- integer(5)., что успешно.Но более общая цель, ?- integer(X)., терпит неудачу !

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

"Надлежащим" (то есть, если вы хотите, чтобы хорошие монотонные предикаты имели декларативный смысл) было бы, чтобы integer/1 вызвал ошибку создания экземпляра назапросы типа ?- integer(X). на том основании, что у него недостаточно информации, чтобы ответить на вопрос в данный момент.Вместо integer/1 вы должны использовать must_be/2 из library(error) для получения этого поведения звука:

?- must_be(integer, X).
ERROR: Arguments are not sufficiently instantiated

must_be/2 ведет себя монотонно, что в целом является хорошим свойством.

Расширение только комментария: проблема в том, что (по крайней мере, если приведенные выше примеры верны), ваш предикат больше не является истинным отношением, потому что цели теперь не являются коммутативными: ?- X = 0, X = Y, addUnique([X,Y,3],3). успешно, но простой обмен порядком целей не даеттот же результат, потому что ?- X = Y, addUnique([X,Y,3], 3), X = 0. терпит неудачу.

Такие явления являются обычным следствием использования мета-логических предикатов.Декларативным решением таких проблем являются ограничения , см., Например, dif/2.Они монотонны, коммутативны и, как правило, намного проще для понимания.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...