2016-05-14 10 views
1

Können Sie mir helfen, einen Fehler zu lösen? Ich verstehe diesen Fehler nicht.rückwärts mit Akkumulator in Prolog - Fehler

reverse(L, R) :- reverse(L, [], R). 
reverse([], R, R). 
reverse([Head|Tail], Acc, R) :- NewAcc is [Head|Acc], reverse(Tail, NewAcc, R). 

? - reverse [1,2,3], X).

Type error: `[]' expected, found `[2|1]' (a compound) ("x" must hold one character) 
+1

'ist/2' wird verwendet, um arithmetische Ausdrücke auszuwerten. '[Head | Acc]' ist kein arithmetischer Ausdruck. Sie können auch die Vereinheitlichung von 'NewAcc = [Head | Acc]' direkt im rekursiven Aufruf von 'reverse' durchführen: 'reverse ([Head | Tail], Acc, R): - reverse (Tail, [Head | Acc] , R) .'. – lurker

+0

* 'is/2' wird verwendet, um arithmetische Ausdrücke auszuwerten. * Was genau bedeutet das? –

+1

Dies bedeutet, dass '' dann '' ein arithmetischer Ausdruck sein muss, der ausgewertet werden kann, was auch bedeutet, dass alle Variablen in '' gebunden sein müssen (einen Wert haben). Sie würden es zum Beispiel verwenden, wie 'X ist (Y + 7)/(2 * log (Z))' und in diesem Fall müssen 'Y' und' Z' einen Wert haben, und Prolog wird den Ausdruck auswerten. Wenn 'X' auch bereits einen Wert hat, wird der Ausdruck erfolgreich sein, wenn er wahr ist, und fehlschlagen, wenn er falsch ist. Viele anfängliche Prolog-Programmierer verwenden irrtümlich 'is/2' als einen allgemeinen Zuweisungsoperator. Prolog hat keine "Zuweisungsoperatoren" an sich *. – lurker

Antwort

4

Ihr Prädikat funktioniert im Prinzip, aber Sie wollen wahrscheinlich Vereinigung (=)/2 anstelle von arithmetischer Auswertung verwenden ist/2 in der rekursiven Ziel:

reverse(L, R) :- 
    reverse(L, [], R). 

reverse([], R, R). 
reverse([Head|Tail], Acc, R) :- 
    NewAcc = [Head|Acc],    % <- here 
    reverse(Tail, NewAcc, R). 

Mit dieser kleinen Änderung Ihres Prädikat Werken :

?- reverse([1,2,3],R). 
R = [3,2,1] 

Wie @lurker in den Kommentaren darauf hingewiesen, können Sie die rekursive Regel kompakter durch die Einbeziehung [Head|Acc] in seine rekursive auszudrücken Ziel wie folgt:

reverse([Head|Tail], Acc, R) :- 
    reverse(Tail, [Head|Acc], R). 

Allerdings könnte man DCGs für diese Aufgabe zu prüfen, wie unter Verwendung, da sie leichter lesbaren Code ergeben:

reverse(L,R) :- 
    phrase(invlist(L),R). 

invlist([]) --> 
    []. 
invlist([H|T]) --> 
    invlist(T), 
    [H]. 

Mit der entsprechenden Abfrage:

?- reverse([1,2,3],R). 
R = [3,2,1] 
+1

And Sie können 'NewAcc = [Head | Acc]' zusammen mit 'reverse (Tail, [Head | Acc], R)' loswerden. :) – lurker

+1

@lurker: Ich habe dieses Detail vollständig ignoriert. Danke für den Hinweis, ich habe es in meine Antwort aufgenommen :-) – tas