![](/img/trans.png)
[英]Capitalize Every Other Letter in a String — take / drop versus head / tail for Lists
[英]Prolog getting head and tail of string
我正试图将我的大脑第一次包裹在Prolog(SWI-Prolog),我正在努力克服我确定的基础知识。 我正试图拿一个像“馅饼”这样的字符串并打印出军事北约拼写它看起来像这样:
spellWord("Pie").
Papa
India
Echo
目前我只是想验证我正在使用[H | T]语法和Write函数。 我的功能是:
spellWord(String) :- String = [H|T], writeChar(H), spellWord(T).
writeChar(String) :- H == "P", print4("Papa").
当打电话给spellWord("Pie")
。 这当前只返回false。
无论您使用的是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)
仅适用于代码,并且会打开不必要的选择点。 相反,根据Prolog标志使用此替换符合chars
和codes
。
历史上,字符首先表示为长度为1的原子。 也就是说,1972年在Prolog 0中。然而,在那里,字符串以左关联方式表示,这有利于后缀匹配。
plur(nil-c-i-e-l, nil-c-i-e-u-x).
从1973年的Prolog I开始,双引号意味着像今天一样的字符列表。
1977年,DECsystem 10 Prolog将双引号的含义更改为字符代码列表,并使用代码代替字符。 这使得一些I / O操作更有效率,但是调试这样的程序要困难得多[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
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
至于你的谓词定义,考虑在头部使用统一。 另外,不要将副作用(打印)与谓词的作用混合在一起。 让顶级(Prolog解释器)为您进行打印。
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.
您的代码存在以下问题:
spellWord(String) :- String = [H|T], writeChar(H), spellWord(T).
当你给这个谓词一个长字符串时,它会用该字符串的尾部调用它自己。 但是当String
为空时,它不能被分割为[H|T]
,因此谓词失败,返回false
。
要解决此问题,您还必须另外定义:
spellWord([]).
这是简短的形式:
spellWord(String) :- String = [].
你的另一个谓词也有问题:
writeChar(String) :- H == "P", print4("Papa").
这里有两个变量, String
和H
这些变量绝不相关。 因此,无论您作为参数传递什么,它都不会影响您用于比较的H
由于==
运算符只进行比较,没有统一, writeChar
失败,返回false
。 这就是为什么根本没有输出的原因。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.