2017-02-06 10 views
1

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

я уже успел сделать это за один предикат:

:- dynamic(test/2). 

test(a,b). 

top(X,Y) :- 
    (test(X,Y), 
    write('Yes'),! 
    ;write('No'),! 
    ). 

Эта версия работает нормально, возвращая «Да», если информация уже существует и «Нет», если он не делает.

Мне было интересно, можно ли сделать это для нескольких prediactes, а не только для 'test/2'; Я попытался заменить предикат 'test' переменной Pred, но, к сожалению, я получаю синтаксическую ошибку, когда пытаюсь ее скомпилировать. Вот моя попытка:

main(Pred,X,Y) :- 
     (Pred(X,Y), 
     write('Yes'),! 
     ;write('No'),! 
    ). 

Возможно ли это сделать что-то вроде этого, и если это то, как бы это было возможно?

Btw Я использую GNU Prolog, если это помогает.

Большое спасибо за помощь: D !!

+1

это не должно быть '->' в если-то-то еще? –

+0

Вы не проверяете наличие предиката. Вы проверяете, верны ли определенные запросы или факты, правильно?Одно дело проверить, существует ли вообще-то Pred' как предикат, а другой - определить, выполняется ли 'test (X, Y)' (или 'call (Pred, X, Y)') для определенного 'X' и/или 'Y'. – lurker

ответ

2

Вы хотите, чтобы call/2 вызывал динамическую цель с аргументами, оцениваемыми во время выполнения. В вашем случае, это было бы call(Pred,X,Y):

main(Pred,X,Y) :- 
    (
     call(Pred,X,Y), 
     write('Yes'),! 
    ) 
    ; 
    (
     write('No'),! 
    ). 

Обратите внимание, что Pred/2 должен разрешить до фактического предиката во время выполнения, и вам нужно будет строить различные правила для каждого числа аргументов.

@ ответ Томас-By, используя (=..)/2 позволяет создать одно правило, со списком аргументов, но с теми же оговорками относительно предикатов существующих, хотя и с дополнительной строкой:

main(Pred,L) :- % where L is a list of args [X,Y|...] 
    Term =.. [Pred | L], 
    (
     Term, 
     write('Yes'),! 
    ) 
    ; 
    (
     write('No'),! 
    ). 

И, как отметил в комментариях @lurker, в любом случае, с помощью (->)/2:

(call(Pred,X,Y) -> write('Yes') ; write('No')) 

или

(Term -> write('Yes') ; write('No')) 

может быть предпочтительнее, поскольку разрушение точек выбора ограничено структурой if-> then else.

+0

Я бы также использовал 'p1 -> p2; p3', который ведет себя как 'p1,! ; p2', а не использовать '(p1,!); (p2,!) '. – lurker

+0

'clause/2' и' current_predicate/1' также могут использоваться, чтобы сориентироваться в том, что уже определено. –

2

Существует оператор = .. для построения терминов, как:

Term =.. [Op,V1,V2] 

не уверен, что в Gnu Прологе.

Использование Sicstus:

xxx(1,2). 

check(Pred,X,Y) :- 
    Term =.. [Pred,X,Y], 
    (Term -> 
    write('Yes') 
    ; write('No')). 

и после загрузки файла:

| ?- check(xxx,1,2). 
Yes 
+0

Надеюсь, вы не против, но я включил информацию, которую вы использовали (с атрибуцией!) В свой ответ, чтобы сделать принятый ответ более полным. Если вы предпочитаете, я могу удалить его. –

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

  • Нет связанных вопросов^_^