Порядок инструкций и рекурсия в прологе

#list #recursion #prolog #logic

#Список #рекурсия #пролог #Логические

Вопрос:

Я только начал работать в прологе, и у меня есть вопрос, касающийся рекурсии.

Я в основном хочу подсчитать, сколько раз определенное значение находится в списке, поэтому, например, у меня есть:

 count( a, [ a, s, d, f, g, a, s, d, a, s ], W ). W = 3.  

Где я хочу подсчитать количество раз, когда «а» находится в списке, и сохранить число в «W».

Правильный ответ таков

 count( _, [], 0 ).  count( A, [B|S], X ) :- A==B, count( A, S, Y ), X is Y   1.  count( A, [B|S], X ) :-   A == B, count( A, S, X ).  

Однако я не понимаю, почему в строке 2 в конце стоит «X равно Y 1». Разве линия не должна быть скорее

 count( A, [A|S], X ) :- Y is X   1, count( A, S, Y ).  

В этом случае мы сначала устанавливаем Y равным 1, затем снова отправляем его на «подсчет» с рекурсией.

Если кто-нибудь может мне помочь, я был бы вам очень признателен!

Ответ №1:

Учтите это, когда будете звонить:

 ?- count(a,[a,s,d,f,g,a,s,d,a,s],W).  

…тогда первый предикат, который соответствует, является count(A,[B|S],X) . Таким образом, это означает, что он видит это так, как count(a,[a|S],X) если S бы amp; X были переменными. X это только W из исходного вызова, так что это все еще переменная.

Предположение, что Y is X 1 это затем оценивается, не имеет смысла, как X и переменная.

Исходный предикат, однако, имеет смысл.

 count(A,[B|S],X) :- A==B, count(A,S,Y), X is Y   1.  

Когда он рекурсирует, он отправляет новую переменную Y во 2-й count/3 предикат (или просто передает ту же переменную в 3-м предикате). И он продолжает делать это до тех пор, пока не достигнет базового случая, когда он, наконец, объединит переменную в 0 . В этот момент он разматывает рекурсию, и теперь он, наконец, может это сделать X is Y 1 (потому Y что это значение) и, следовательно X , теперь является значением.

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

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

1. о, ух ты, теперь я понимаю! Большое спасибо!

Ответ №2:

 count( A, [B|S], X ) :- A==B, count( A, S, Y ), X is Y   1.  

Это означает: Если S содержит Y вхождения A , и A == B , то [B | S] содержит еще одно вхождение A .

Например, представьте, что мы добираемся сюда, подсчитывая вхождения prolog [prolog, prolog, prolog] . [B | S] = [prolog, prolog, prolog] , итак S = [prolog, prolog] . Количество вхождений prolog in S равно 2, так что мы должны были бы Y = 2 . Количество вхождений prolog in [B | S] равно 3, так что у нас должно быть X = 3 . Как только мы узнаем Y = 2 , то X is Y 1 вычисляем это правильное значение X .

 count( A, [A|S], X ) :- Y is X   1, count( A, S, Y ).  

Это означало бы: если [A | S] содержит X вхождения A , то S содержит еще одно вхождение A . Этого не может быть.

Снова используя приведенный выше пример: Явно [A | S] = [prolog, prolog, prolog] содержит 3 вхождения prolog , поэтому X = 3 должно сохраняться. Но тогда Y должно было бы быть 4, и цель в теле попыталась бы доказать, что S = [prolog, prolog] содержит 4 вхождения prolog . Этого явно не может быть.

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