2016-12-20 5 views
0

Ich versuche herauszufinden, warum dieses Stück Code wirklich gut funktioniert. Ich verstehe nichts von dem, was dort vor sich geht, wie Counter1 mit 0 vereinheitlicht und dann mit 1 vereinheitlicht, und so weiter. Die Counter-Variable scheint mir mehr Sinn zu machen, aber die andere ...Warum vereinheitlicht das Is/2 Prädikat eine Variable mit Null?

Die folgenden zwei Regeln definieren das Prädikat numberOfElements/2, das zählt, wie viele Elemente eine gegebene Liste hat.

numberOfElements([], 0). 
numberOfElements([_|Tail], Counter):- 
    numberOfElements(Tail,Counter1), 
    Counter is Counter1 + 1 . 
+0

Haben Sie versucht, einen 'trace' auf einem einfachen Beispiel (* zB *, eine Liste von 2 Elementen zu tun - geben Sie' trace.' an der Eingabeaufforderung, dann ' numberOfElements ([a, b], N) .')? Du solltest es versuchen. Dies ist ein * rekursives * Prädikat. So wird es sich selbst aufrufen, bis es den Basisfall erreicht (das erste Argument ist schließlich '[]') und das zweite Argument als '0' instanziiert. Dann erhalten Sie 'Counter ist Counter1 + 1' (mit' Counter1' als '0'), die dann zur nächsten Stufe des rekursiven Aufrufs usw. zurückkehrt. Sind Sie mit der Rekursion im Allgemeinen vertraut? – lurker

+0

Ich versuche zu wissen, ** WARUM ** die Counter1-Variable vereinheitlicht mit einer Null, ich habe keine Spur versucht (ich weiß nicht einmal, was das ist), weiß ich bereits über Rekursivität und das meiste, was geht auf außer was meine Frage fragt. – newbie

+1

Ich erklärte warum. Aufgrund der Rekursion bis zum Basisfall wird 'Counter1' mit' 0' vereinheitlicht. – lurker

Antwort

1

Ich versuche, mit einem Beispiel zu erklären.

Angenommen, Sie rufen numberOfElements([a, b, c], C).

Die einzige Klausel anwendbar ist die zweite, verwerfen, so dass die Spitze der Liste (a) vereinigen Tail mit [b, c] und den variablen C mit den Variablen Counter.

Dann numberOfElemens/2 rufen Sie sich mit Tail (vereinheitlicht mit [b, c]) und eine neue Variable, Counter1.

Nun ist die einzige Klausel anwendbar ist (wieder) die zweite, so werfen Sie den Kopf der Liste (b), vereinigt Tail mit [c] und den variablen Counter1 (dem ersten Anruf) mit den variablen Counter (den zweiten Anruf).

Dann numberOfElemens/2 rufen Sie sich erneut mit Tail (vereinheitlicht mit [c]) und eine neue Variable Counter1.

Nun ist die einzige Klausel anwendbar ist (zum dritten Mal) die zweiten, so werfen Sie den Kopf der Liste (c), vereinigt Tail mit [] (der leeren Liste) und die Variable Counter1 (der zweiten Anrufs) mit der Variablen Counter (des dritten Aufrufs).

Dann numberOfElemens/2 rufen Sie sich wieder mit Tail (vereinheitlicht mit leere Liste) und eine neue Variable Counter1.

Diesmal ist die einzige anwendbare Klausel die erste (die Liste ist leer), so dass Counter1 des dritten Aufrufs mit Null vereinheitlicht wird.

Jetzt wird Counter is Counter1 + 1 im dritten Aufruf ausgeführt, Counter1 ist Null, so werden Counter 1.

Aber Counter im dritten Anruf, Unified mit Counter1 in der zweiten; so wird es im zweiten Aufruf Counter is Counter1 + 1 ausgeführt. Counter1 ist vereinigt mit 1 so Counter geworden 2.

Aber Counter, in dem zweiten Aufruf, mit Counter1 in der ersten einheitlichen ist; so wird es Counter is Counter1 + 1 im ersten Anruf ausgeführt. Counter1 ist einheitlich mit 2 so Counter 3. worden

Daran erinnernd, dass Counter im ersten Anruf mit den ursprünglichen C vereinigt wird, so C mit 3 vereinigt ist.

Ich versuche, wie folgt zusammenfassen

counter([a, b, c], C) 

---> counter([_ | [b, c]], C = COUNTER(1)) 

     ---> counter([_ | [c]], COUNTER1(1) = COUNTER(2)) 

      ---> counter([_ | []], COUNTER1(2) = COUNTER(3)) 

       ---> counter([], COUNTER1(3) = 0) 

      ---> COUNTER(3) is COUNTER1(3) + 1 = 0 + 1 = 1 

     ---> COUNTER(2) is COUNTER1(2) + 1 = COUNTER(3) + 1 = 1 + 1 = 2 

---> C = COUNTER(1) is COUNTER1(1) + 1 = COUNTER(2) + 1 = 2 + 1 = 3 
+0

Super! Vielen Dank. Ich verstand es perfekt, dieses verrückte Backtracking, LOL. – newbie

+1

@newbie - Gern geschehen; und, ja: Prolog ist am Anfang etwas schwierig; aber faszinierend. – max66

+2

@newbie das ist die Abwicklung von verschachtelten rekursiven Aufrufe, nicht wirklich Backtracking. – lurker

Verwandte Themen