2015-03-23 3 views
2

Я пытаюсь создать альтернативу findall в Прологе.Альтернатива findall

Что у меня есть:

solutions(A,T,S) :- 
    T, 
    assert(temp(A)), 
    fail. 
solutions(A,T,S) :- 
    obtain([],S). 

obtain(X,S) :- 
    retract(temp(A)), 
    obtain([A|X],S). 
obtain(S,S). 

Это, однако, дает мне противоречивые результаты. Что не так? Заранее спасибо.

+1

Можете ли вы описать, что является * непоследовательным * в ваших результатах? – lurker

+0

Возможно, использование 'assertz' вместо' assert' решит эту загадочную несогласованность. –

+1

@EugeneSh. Я считаю, что 'assert' и' assertz' делают то же самое. :) – lurker

ответ

2

Существует несколько проблем с вашей реализацией.

  1. В начале нет очистки. Добавить retractall(temp(_)) до T,

  2. obtain/2 удастся с большим количеством различных ответов, потому что retract(temp(A)) даст ответы на многие вопросы, и потому, что вторая статья obtain(S,S) всегда будет решением. Это можно сохранить, добавив разрез после retract.

    | ?- obtain([],S). 
    S = [2,1] ? ; 
    S = [1] ? ; 
    S = [2] ? ; 
    S = [] ? ; 
    no 
    

  3. Возможно, вы захотите изменить заказ либо с помощью asserta/1, либо путем переопределения obtain/2.

  4. Ваше определение не является повторным. Это невозможно решить легко. Вам понадобится либо некоторая gensym, либо функциональность, либо еще более сложные функции.

  5. Для точной печати assert/1 против assertz/1 см. this answer.