Пролог получение головы и хвоста строки
Я пытаюсь обернуть свой мозг вокруг Пролога в первый раз (SWI-Prolog), и я борюсь с тем, что я уверен, являются основами. Я пытаюсь взять строку, такую как" пирог", и распечатать военную орфографию НАТО, чтобы она выглядела примерно так:
spellWord("Pie").
Papa
India
Echo
В настоящее время я просто пытаюсь проверить, что я использую синтаксис [H|T] и правильно пишу функцию. Моя функция:
spellWord(String) :- String = [H|T], writeChar(H), spellWord(T).
writeChar(String) :- H == "P", print4("Papa").
при вызове spellWord("Pie")
. это в настоящее время просто возвращается ложный.
3 ответов
SWI-Prolog имеет несколько различных представлений того, что вы можете назвать "строками".
- список кодов символов (Юникод);
- список символов (однобуквенные атомы);
- строки, которые являются "атомарными" объектами и могут управляться только со встроенными предикатами для строк;
- и, наконец, конечно, атомы.
вы должны прочитать документацию, но на данный момент у вас есть по крайней мере два выбор.
выбор 1: используйте флаг для создания списков кодов строк с двойными кавычками
$ 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].
на данный момент, ваш подход должен работать, так как теперь у вас есть список.
выбор 2: используйте новый синтаксис списка кода с обратными тиками
?- X = `abc`.
X = [97, 98, 99].
и, конечно же, есть предикаты, которые преобразуются между атомами, списками кода, списками символов и строками. Итак, чтобы составить список символов (односимвольных атомов), вы есть:
atom_chars/2
char_code/2
string_chars/2
Что касается определения предиката, рассмотрите возможность использования объединения в голове. Кроме того, не смешивайте побочные эффекты (печать) с тем, что делает предикат. Пусть верхний уровень (интерпретатор пролога) сделает печать за вас.
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).
и так:
?- word_nato(`Pie`, Nato).
Nato = ['Papa', 'India', 'Echo'].
я использовал символы (однобуквенные атомы) вместо кодов символов, потому что их легче писать.
и, наконец, вы можете использовать следующий флаг, и set_prolog_flag/2
во время выполнения, чтобы изменить, как Prolog обрабатывает строку, заключенную в двойные кавычки.
например:
$ 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.
независимо от системы Prolog, которую вы используете, и если вам не нужно
поддерживайте существующий код, придерживайтесь set_prolog_flag(double_quotes, chars)
. Это работает в много
системы
как B, GNU, IF, IV, Minerva, SICStus, SWI, YAP. Так это сейф
ставка. Другие параметры, упомянутые @Boris, трудно отлаживать. Один даже специфичен для SWI
только.
?- set_prolog_flag(double_quotes, chars).
true.
?- L = "abc".
L = [a, b, c].
С
library(double_quotes)
эти строки могут быть напечатаны более компактно.
в SWI, лучшее, что вы можете сделать, это положить в ваш .swiplrc
строки:
:- set_prolog_flag(back_quotes, string).
:- set_prolog_flag(double_quotes, chars).
:- use_module(library(double_quotes)).
для вашего конкретного примера, хорошая идея избежать произвести побочные эффекты немедленно. Вместо этого рассмотрим определение отношения между словом и написанием:
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".
и вот ваше первоначальное определение. Однако большую часть времени, скорее, придерживайтесь чистого ядра.
spellWord(Ws) :-
word_spelling(Ws, Xs),
format("~s", [Xs]).
также обратите внимание, что SWI встроенный library(pio)
работает только для
коды и оставляет ненужные точки выбора открытыми. Вместо этого используйте этот
замена
который работает для chars
и codes
в зависимости от флага Prolog.
исторически символы были впервые представлены в виде атомов длины один. То есть 1972 в прологе 0. Однако, там, струны были представлены в лево-ассоциативным образом, который способствовал соответствующий суффикс.
plur(nil-c-i-e-l, nil-c-i-e-u-x).
начиная с Prolog I, 1973, двойные кавычки означали список символов как сегодня.
в 1977 году DECsystem 10 Prolog изменен значение двойных кавычек к спискам символов коды и используемые коды вместо символов. Это сделало некоторые операции ввода-вывода немного эффективнее, но сделал отладку таких программ намного более трудный [76,105,107,101,32,116,104,105,115] - вы можете его прочитать?
ISO Prolog поддерживает оба. Есть флаг double_quotes
что
указывает как двойные кавычки
понял. Также,
характер, связанные встроенные присутствуют для обоих:
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
проблемы с вашим кодом:
spellWord(String) :- String = [H|T], writeChar(H), spellWord(T).
когда вы даете этому предикату длинную строку, он будет вызывать себя с хвостом этой строки. Но когда!--4-- > пусто, его нельзя разделить на [H|T]
, поэтому предикат терпит неудачу, возвращая false
.
чтобы исправить это, вы должны дополнительно определить:
spellWord([]).
это короткая форма:
spellWord(String) :- String = [].
ваш другой предикат также имеет проблема:
writeChar(String) :- H == "P", print4("Papa").
у вас есть две переменные здесь String
и H
. Эти переменные никоим образом не связаны. Поэтому независимо от того, что вы передаете в качестве параметра, это не повлияет на H
что вы используете для сравнения. И с тех пор ==
оператор только делает сравнение, без объединения,writeChar
терпит неудачу в этот момент, возвращаясь false
. Именно по этой причине вообще нет выхода.