2015-05-23 3 views
1

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

predicate(L1, Restriction) :- 
    foreach(member(Var,L1), Var = 1), 
    Restriction. 

Но когда я пишу в консоли:

? - predicate([A,B,C], A==1). 

или

? - predicate([A,B,C], B==1). 

или

? - predicate([A,B,C], A==B). 

все они возвращают ложь.

Не должно быть A, B и C быть эквивалентно 1 после цикла foreach?

+1

Имейте в виду, что не существует понятие «присвоение» в прологе. Вместо этого он использует «унификацию». Это важное различие. – Enigmativity

ответ

1

Paulo хорошо объяснил, в чем проблема (+1). Может быть, вы должны исправить свой код, как

predicate(L1, Restriction) :- 
    maplist(=(1), L1), 
    Restriction. 

, который дает ожидаемый результат

?- predicate([A,B,C], A==1). 
A = B, B = C, C = 1. 
+0

Я могу видеть, как maplist выполняет здесь свою работу. Но что, если я хочу сделать все элементы списка равными соответствующим значениям другого списка? Скажем, что L1 = [A, B, C] и L2 = [1,2,3]. Как я должен подходить к реализации предиката так, чтобы я назначил 1 A, 2-B и 3-C и только затем проверил Ограничение (которое включает A, B, C)? –

+0

Используйте 'maplist/3' вместо' maplist/2': 'maplist ((=), L1, L2)'. –

+0

Это действительно работает. Спасибо! Я также заметил, что просто запись L1 = L2 приводит к такому же результату. Я не представлял, что то, что я пытаюсь достичь, было настолько тривиальным. –

1

Проблема заключается в том, как работает предикат foreach/2. Первый аргумент работает как генератор , а второй аргумент работает как тест для каждого решения генератора. Но предикат создает связь , где каждый элемент является копией второго аргумента. Из-за этого копирования переменные в генераторе никогда не получают экземпляр (поскольку вы копируете копии). Эта семантика может быть проиллюстрирована следующим запросом:

?- foreach(member(Var, [A,B,C]), Var = 1), var(A), var(B), var(C). 
true. 

Как ваше ограничение на predicate/2 звонков является равенства теста и переменный не равен целым число, все звонки терпят неудачу.

Если вы намерены создать список заданной длины со всеми элементами, равными заданному термину, существует несколько способов его выполнения. Например, используя только стандартные встроенные предикаты:

?- findall(1, between(1, 3, _), List). 
List = [1, 1, 1]. 
Смежные вопросы