Предложение Prolog вызывается при каждом обращении к значению, полученному из предложения

#prolog

#prolog

Вопрос:

Пожалуйста, потерпите меня, потому что я новичок в логическом программировании. Я пишу предложение Prolog, которое должно быть успешным, если другое предложение — get_cards_by_suit/3 — возвращает список только с одним элементом. Однако кажется, что всякий раз, когда я использую возвращаемый список, предложение get_cards_by_suit вызывается снова само по себе. Я понятия не имею, почему это происходит, и я потратил часы, пытаясь разобраться в этом.

Вот предложение, с которым у меня возникли проблемы:

 find_strongest_card(CardPile, TrumpSuit, StrongestCard, Reason) :-
   %if there is one and only one trump suit cards in the pile, then that card is the strongest card
   get_cards_by_suit(CardPile, TrumpSuit, AllTrumpCardsInCardPile),
   write(AllTrumpCardsInCardPile), nl,
   %if there is only one card in the pile/list, then clause succeeds
   AllTrumpCardsInCardPile = [StrongestCard],
   Reason = card_is_trump_suit.
 

И вот предложение get_cards_by_suit:

 get_cards_by_suit([], _, []).

get_cards_by_suit([FirstCard | RemainingCards], Suit, CardsOfGivenSuit) :-
   get_card_suit(FirstCard, FirstCardSuit),
   FirstCardSuit = Suit,
   CardsOfGivenSuit = [FirstCard | OtherCardsOfGivenSuit],
   get_cards_by_suit(RemainingCards, Suit, OtherCardsOfGivenSuit).

get_cards_by_suit([_ | RemainingCards], Suit, CardsOfGivenSuit) :-
   get_cards_by_suit(RemainingCards, Suit, CardsOfGivenSuit).
 

В предложение find_strongest_card я включил оператор write, который выводит значение, возвращаемое get_cards_by_suit, чтобы показать, как повторяется предложение.

Вот результат, когда я делаю следующий запрос: Запрос:

 find_strongest_card([0, 1, 2, 3, 5, 4, 5, 13, 11, 12, 17, 16, 15, 13], clubs, Card, Reason).
 

Вот результат:

 [0,1,2,3,5,4,5]
[0,1,2,3,5,4]
[0,1,2,3,5,5]
[0,1,2,3,5]
[0,1,2,3,4,5]
[0,1,2,3,4]
[0,1,2,3,5]
[0,1,2,3]
[0,1,2,5,4,5]
[0,1,2,5,4]
[0,1,2,5,5]
[0,1,2,5]
[0,1,2,4,5]
[0,1,2,4]
[0,1,2,5]
[0,1,2]
[0,1,3,5,4,5]
[0,1,3,5,4]
[0,1,3,5,5]
[0,1,3,5]
[0,1,3,4,5]
[0,1,3,4]
[0,1,3,5]
[0,1,3]
[0,1,5,4,5]
[0,1,5,4]
[0,1,5,5]
[0,1,5]
[0,1,4,5]
[0,1,4]
[0,1,5]
[0,1]
[0,2,3,5,4,5]
[0,2,3,5,4]
[0,2,3,5,5]
[0,2,3,5]
[0,2,3,4,5]
[0,2,3,4]
[0,2,3,5]
[0,2,3]
[0,2,5,4,5]
[0,2,5,4]
[0,2,5,5]
[0,2,5]
[0,2,4,5]
[0,2,4]
[0,2,5]
[0,2]
[0,3,5,4,5]
[0,3,5,4]
[0,3,5,5]
[0,3,5]
[0,3,4,5]
[0,3,4]
[0,3,5]
[0,3]
[0,5,4,5]
[0,5,4]
[0,5,5]
[0,5]
[0,4,5]
[0,4]
[0,5]
[0]
Card = 0,
Reason = card_is_trump_suit
 

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

Чего мне не хватает?

Редактировать: вот некоторая дополнительная информация:

Это предложение get_card_suit/2, используемое в get_cards_by_suit/3 :

 get_card_suit(Card, clubs) :-
   mod(Card, 24) < 6.

get_card_suit(Card, diamonds) :-
   mod(Card, 24) >= 6,
   mod(Card, 24) < 2 * 6.

get_card_suit(Card, hearts) :-
   mod(Card, 24) >= 2 * 6,
   mod(Card, 24) < 3 * 6.

get_card_suit(Card, spades) :-
   mod(Card, 24) >= 3 * 6,
   mod(Card, 24) < 4 * 6.
 

I also tested something else out. I replaced the get_cards_by_suit/3 definition with the following:

 get_cards_by_suit(List, Suit, [4, 5, 6, 7, 7]) :-
   write(List), nl.
 

Когда я снова использую запрос предложения find_strongest_card (но удаляя write(AllTrumpCardsInCardPile) команду, я получаю следующий вывод:

 [0,1,2,3,5,4,5,13,11,12,17,16,15,13]
false.
 

Однако, когда я добавляю исходные определения предложения get_cards_by_suit / 3 за тем, которое я создал для тестирования (как показано ниже), я снова получаю аналогичную ошибку
определение get_cards_by_suit / 3:

 get_cards_by_suit(List, Suit, [4, 5, 6, 7, 7]) :-
   write(List), nl.

get_cards_by_suit([], _, []).

get_cards_by_suit([FirstCard | RemainingCards], Suit, CardsOfGivenSuit) :-
   get_card_suit(FirstCard, FirstCardSuit),
   FirstCardSuit = Suit,
   CardsOfGivenSuit = [FirstCard | OtherCardsOfGivenSuit],
   get_cards_by_suit(RemainingCards, Suit, OtherCardsOfGivenSuit).

get_cards_by_suit([_ | RemainingCards], Suit, CardsOfGivenSuit) :-
   get_cards_by_suit(RemainingCards, Suit, CardsOfGivenSuit).
 

На этот раз вывод:

 [0,1,2,3,5,4,5,13,11,12,17,16,15,13]
[1,2,3,5,4,5,13,11,12,17,16,15,13]
[2,3,5,4,5,13,11,12,17,16,15,13]
[3,5,4,5,13,11,12,17,16,15,13]
[5,4,5,13,11,12,17,16,15,13]
[4,5,13,11,12,17,16,15,13]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[4,5,13,11,12,17,16,15,13]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[5,4,5,13,11,12,17,16,15,13]
[4,5,13,11,12,17,16,15,13]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[4,5,13,11,12,17,16,15,13]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[3,5,4,5,13,11,12,17,16,15,13]
[5,4,5,13,11,12,17,16,15,13]
[4,5,13,11,12,17,16,15,13]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[4,5,13,11,12,17,16,15,13]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[5,4,5,13,11,12,17,16,15,13]
[4,5,13,11,12,17,16,15,13]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[4,5,13,11,12,17,16,15,13]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[2,3,5,4,5,13,11,12,17,16,15,13]
[3,5,4,5,13,11,12,17,16,15,13]
[5,4,5,13,11,12,17,16,15,13]
[4,5,13,11,12,17,16,15,13]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[4,5,13,11,12,17,16,15,13]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[5,4,5,13,11,12,17,16,15,13]
[4,5,13,11,12,17,16,15,13]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[4,5,13,11,12,17,16,15,13]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[3,5,4,5,13,11,12,17,16,15,13]
[5,4,5,13,11,12,17,16,15,13]
[4,5,13,11,12,17,16,15,13]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[4,5,13,11,12,17,16,15,13]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[5,4,5,13,11,12,17,16,15,13]
[4,5,13,11,12,17,16,15,13]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[4,5,13,11,12,17,16,15,13]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[5,13,11,12,17,16,15,13]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
[13,11,12,17,16,15,13]
[11,12,17,16,15,13]
[12,17,16,15,13]
[17,16,15,13]
[16,15,13]
[15,13]
[13]
[]
Card = 0,
Reason = card_is_trump_suit 
 

Действительно странно. Я ценю любую помощь

Комментарии:

1. get_cards_by_suit/3 неясен, с несколькими неопределенными предикатами. Не могли бы вы добавить их тоже, пожалуйста?

2. @DavidTonhofer Я добавил предикат get_card_suit/2, используемый get_cards_by_suit/3 . Спасибо!

Ответ №1:

В get_cards_by_suit/3 unification FirstCardSuit = Suit используется как «защита», чтобы решить, продолжать ли (потому что у нас есть правильный костюм) или прервать (потому FirstCardSuit что не является of Suit ). Если мы прервемся, то ограничимся 4-м пунктом: get_cards_by_suit([_ | RemainingCards], Suit, CardsOfGivenSuit) .

Однако, если мы не прервемся, Prolog сохранит (неправильную) альтернативу get_cards_by_suit([_ | RemainingCards], Suit, CardsOfGivenSuit) открытой и попробует ее позже. Вы должны указать ему, чтобы он отбросил эту альтернативу.

Добавьте сокращение ! после guard FirstCardSuit = Suit : FirstCardSuit = Suit,!,... , таким образом, придерживаясь этой альтернативы. Третье предложение не будет опробовано позже.

Комментарии:

1. Это сработало! Большое вам спасибо! Вы экономите мне часы и часы боли