2016-04-13 13 views
7

Ich versuche, mein Gehirn um Prolog zum ersten Mal zu wickeln (SWI-Prolog) und ich kämpfe mit, was ich bin sicher, sind die Grundlagen. Ich versuche, eine Zeichenfolge wie „Kuchen“ zu nehmen und die militärische NATO Rechtschreibung drucken aus ihm so etwas wie folgt aussehen:Prolog Kopf und Schwanz der Schnur bekommen

spellWord("Pie"). 
Papa 
India 
Echo 

Derzeit Ich versuche nur, um sicherzustellen, dass ich mit den Tasten [ H | T] Syntax und Schreibfunktion korrekt. Meine Funktion ist:

spellWord(String) :- String = [H|T], writeChar(H), spellWord(T). 

writeChar(String) :- H == "P", print4("Papa"). 

Wenn ein Anruf zu spellWord("Pie") machen. Dies gibt derzeit nur falsch zurück.

Antwort

6

SWI-Prolog hat verschiedene Darstellungen von "Strings".

  • Liste der Zeichencodes (Unicode);
  • Liste der Zeichen (Ein-Buchstaben-Atome);
  • Strings, die "atomare" Objekte sind und nur mit den integrierten Prädikaten für Strings manipuliert werden können;
  • Und schließlich, natürlich, Atome.

Sie sollten die Dokumentation lesen, aber für jetzt haben Sie mindestens zwei Möglichkeiten.

Wahl 1: ein Flag Verwenden Sie Strings in doppelten Anführungszeichen Code-Listen

$ swipl --traditional 
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.3.19-57-g9d8aa27) 
Copyright (c) 1990-2015 University of Amsterdam, VU Amsterdam 
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software, 
and you are welcome to redistribute it under certain conditions. 
Please visit http://www.swi-prolog.org for details. 

For help, use ?- help(Topic). or ?- apropos(Word). 

?- X = "abc". 
X = [97, 98, 99]. 

An diesem Punkt zu machen, sollte Ihr Ansatz arbeiten, wie Sie jetzt eine Liste haben.

Wahl 2: Verwenden Sie die neue Codeliste Syntax mit Back-Zecken

?- X = `abc`. 
X = [97, 98, 99]. 

Und natürlich gibt es Prädikate, die zwischen den Atomen, Codelisten, char-Listen und Strings konvertieren . Also, um eine Liste von Zeichen zu machen (ein Zeichen Atome), Sie haben:

  • atom_chars/2
  • char_code/2
  • string_chars/2

Wie für Ihre Prädikat Definition betrachten Vereinigung mit in der Kopf. Mischen Sie auch keine Nebenwirkungen (Drucken) mit dem, was das Prädikat tut. Lassen Sie die oberste Ebene (der Prolog-Interpreter) das Drucken für Sie erledigen.

nato(p, 'Papa'). 
nato(i, 'India'). 
nato(e, 'Echo'). 
% and so on 

word_nato([], []). 
word_nato([C|Cs], [N|Ns]) :- 
    char_code(Char, C), 
    char_type(U, to_lower(Char)), 
    nato(U, N), 
    word_nato(Cs, Ns). 

Und mit diesem:

?- word_nato(`Pie`, Nato). 
Nato = ['Papa', 'India', 'Echo']. 

Ich benutzte Zeichen (Ein-Buchstaben-Atome) anstelle von Zeichencodes, weil diese leichter zu schreiben.


Und schließlich können Sie das folgende Flag und set_prolog_flag/2 zur Laufzeit ändern, wie Prolog eine Zeichenfolge behandelt in doppelten Anführungszeichen eingeschlossen.

Zum Beispiel:

$ swipl 
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.3.19-40-g2bcbced) 
Copyright (c) 1990-2015 University of Amsterdam, VU Amsterdam 
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software, 
and you are welcome to redistribute it under certain conditions. 
Please visit http://www.swi-prolog.org for details. 

For help, use ?- help(Topic). or ?- apropos(Word). 

?- current_prolog_flag(double_quotes, DQs). 
DQs = string. 

?- string("foo"). 
true. 

?- set_prolog_flag(double_quotes, codes). 
true. 

?- X = "foo". 
X = [102, 111, 111]. 

?- set_prolog_flag(double_quotes, chars). 
true. 

?- X = "foo". 
X = [f, o, o]. 

?- set_prolog_flag(double_quotes, atom). 
true. 

?- X = "foo". 
X = foo. 
+0

Wie würde ich arbeiten, um die Eingabe in einfache Anführungszeichen zu akzeptieren, z. B. "Kuchen" – donsavage

+0

@donsavage Verwenden Sie zuerst das entsprechende Konversionsprädikat. Ich habe sie in der obigen Antwort aufgeführt. –

+1

Es gibt auch die Option 'set_prolog_flag (double_quotes, chars)' – false

7

Unabhängig von der Prolog-System Sie verwenden, und es sei denn, Sie halten vorhandenen Code haben, halten Sie sich an set_prolog_flag(double_quotes, chars). Dies funktioniert in many systems wie B, GNU, IF, IV, Minerva, SICStus, SWI, YAP. Es ist also eine sichere Wette. Die anderen von @Boris genannten Optionen sind schwer zu debuggen. Eines ist sogar spezifisch nur für SWI .

?- set_prolog_flag(double_quotes, chars). 
true. 

?- L = "abc". 
L = [a, b, c]. 

Mit library(double_quotes) können diese Saiten kompakter gedruckt werden.

In SWI, das Beste, was Sie tun können, ist in Ihren .swiplrc die Zeilen zu setzen:

:- set_prolog_flag(back_quotes, string). 
:- set_prolog_flag(double_quotes, chars). 
:- use_module(library(double_quotes)). 

Für Ihr konkretes Beispiel ist es eine gute Idee ist, Nebenwirkungen sofort zu vermeiden, produzieren. sollten Sie stattdessen eine Beziehung zwischen einem Wort definieren, und der Schreibweise:

word_spelling(Ws, Ys) :- 
    phrase(natospelling(Ws), Ys). 

natospelling([]). 
natospelling([C|Cs]) --> 
    {char_lower(C, L)}, 
    nato(L), 
    "\n", 
    natospelling(Cs). 

nato(p) --> "Papa". 
nato(i) --> "India". 
nato(e) --> "Echo". 

char_lower(C, L) :- 
    char_type(L, to_lower(C)). 

?- word_spelling("Pie",Xs). 
Xs = "Papa\nIndia\nEcho\n". 

?- word_spelling("Pie",Xs), format("~s",[Xs]). 
Papa 
India 
Echo 
Xs = "Papa\nIndia\nEcho\n". 

Und hier ist Ihre ursprüngliche Definition. Meistens bleibt es jedoch bei dem reinen Kern.

spellWord(Ws) :- 
    word_spelling(Ws, Xs), 
    format("~s", [Xs]). 

Beachten Sie auch, dass SWI eingebauten in library(pio) nur für Codes funktioniert und lässt unnötige Wahl-Punkte offen. Verwenden Sie stattdessen this replacement , die je nach Prolog-Flag für chars und codes funktionieren.

Historisch wurden Zeichen zuerst als Atome der Länge eins dargestellt. Das heißt, 1972 in Prolog 0. Dort wurden jedoch die Strings in einer linksassoziativen Weise dargestellt, was das Suffix-Matching erleichterte.

plur(nil-c-i-e-l, nil-c-i-e-u-x). 

Beginnend mit Prolog I, 1973 bedeutete doppelte Anführungszeichen eine Liste von wie heute Zeichen.

Im Jahr 1977 änderte DECsystem 10 Prolog die Bedeutung der doppelten Anführungszeichen in Listen von Zeichencodes und verwendeten Codes anstelle von Zeichen. Dies machte einige E/A-Operationen ein wenig effizienter, aber machte das Debuggen solcher Programme viel schwieriger [76,105,107,101,32,116,104,105,115] - können Sie es lesen?

ISO Prolog unterstützt beides. Es gibt eine Flagge double_quotes, die how double quotes are interpreted angibt.Auch Charakter im Zusammenhang Einbauten vorhanden sind, für beide:

char_code/2 

atom_chars/2, number_chars/2, get_char/1/2, peek_char/1/2, put_char/1/2 

atom_codes/2, number_codes/2, get_code/1/2, peek_code/1/2, put_code/1/2 
1

Die Probleme mit Ihrem Code sind:

spellWord(String) :- String = [H|T], writeChar(H), spellWord(T). 

Wenn Sie dieses Prädikat eine lange Zeichenfolge geben, es sich mit dem Schwanz aufruft dieser Zeichenfolge. Aber wenn String leer ist, kann es nicht in [H|T] aufgeteilt werden, daher schlägt das Prädikat fehl und gibt false zurück.

Um dies zu beheben, müssen Sie zusätzlich definieren:

spellWord([]). 

Dies ist die Kurzform von:

spellWord(String) :- String = []. 

Ihre anderen Prädikat hat auch ein Problem:

writeChar(String) :- H == "P", print4("Papa"). 

Sie haben hier zwei Variablen, String und H. Diese Variablen stehen in keinem Zusammenhang. Egal, was Sie als Parameter übergeben, es beeinflusst nicht die H, die Sie für den Vergleich verwenden. Und da der Operator == nur einen Vergleich ohne Vereinheitlichung durchführt, schlägt writeChar an diesem Punkt fehl und gibt false zurück. Aus diesem Grund gibt es überhaupt keine Ausgabe.

+1

Es gibt immer noch das Problem mit dem, was Sie eine Zeichenfolge nennen und ob es eine Liste ist. Wenn Sie nur den neuesten SWI-Prolog installieren und eine Zeichenkette zwischen doppelte Anführungszeichen eingeben, wie in '" foo "', ist das _most definitiv_ keine Liste, sondern ein atomares Objekt. –

+1

PS. Selbst wenn das Prädikat 'spellWord/1' fehlschlägt, sollte jedes Element der Liste ausgedruckt werden. In gewisser Weise macht es das, was es beabsichtigt hat. –