String 找出第一个字母是否是元音序言

String 找出第一个字母是否是元音序言,string,text,prolog,String,Text,Prolog,我已经习惯了过程编程语言,我也在为prolog而挣扎——缺乏在线资源也是一个令人沮丧的问题 获取给定变量的第一个字符并检查它是否是元音的最“prolog”-y方式是什么 我想这就是我想要的?这都是伪代码——但这就是你解决它的方法吗 isVowel(Word) :- vowels = [a, e, i, o, u], firstLetter(Word[0]), ( firstLetter in vowels -> Vow

我已经习惯了过程编程语言,我也在为prolog而挣扎——缺乏在线资源也是一个令人沮丧的问题

获取给定变量的第一个字符并检查它是否是元音的最“prolog”-y方式是什么

我想这就是我想要的?这都是伪代码——但这就是你解决它的方法吗

isVowel(Word) :-    
    vowels = [a, e, i, o, u],
    firstLetter(Word[0]),
    (
        firstLetter in vowels ->
            Vowel!
        ; Not a vowel!
    ).
非常感谢


奥利

在序言中,您为谓词编写明确的子句(规则)。谓词描述逻辑关系。例如,如果给定的参数是元音,则可能有一个谓词
is_vowel/1
,该谓词为true

is_vowel(Letter):-
    member(Letter, "aeiouAEIOU").
要查看单词是否以元音开头,必须记下第一个字母:

starts_with_vowel(Word):-
    Word = [First|_],
    is_vowel(First).
现在,您可以同时执行统一和模式匹配,如下所示:

starts_with_vowel([FirstLetter|_]):-
    is_vowel(FirstLetter).
几个示例查询:

?- starts_with_vowel("Italy").
true ;
false.

?- starts_with_vowel("Vietnam").
false.

?- Letters = [_|"pple"], starts_with_vowel(Letters), string_to_atom(Letters, Word).
Letters = [97, 112, 112, 108, 101],
Word = apple ;
Letters = [101, 112, 112, 108, 101],
Word = epple ;
Letters = [105, 112, 112, 108, 101],
Word = ipple ...

这可以通过几种方式实现。在这个特殊的解决方案中,我使用确定子句语法(DCG)

此外,答案有点取决于“单词”是什么。如果是字符代码列表,则满足以下条件:

starts_with_vowel --> vowel, dcg_end.
vowel --> [X], {memberchk(X, [0'a,0'A,0'e,0'E,0'i,0'I,0'o,0'O,0'u,0'U])}.
dcg_end(_, []).
使用示例:

?- phrase(starts_with_vowel, `answer`).
true.
?- phrase(starts_with_vowel, `question`).
false.
注:请注意,此处反引号的使用是针对SWI7的。在其他序言中,代码列表将出现在双引号内


如果一个单词是另一个单词,那么首先需要将其转换为代码。例如,
atom\u代码(答案,代码)
如果一个单词由一个原子表示。

您已经得到了答案,但是:

不要做
member
,或
memberchk
。相反,只需使用表格:

vowel(a).
vowel(e).
vowel(i).
vowel(o).
vowel(u).
然后,你不说你有什么样的变量。如果你有一个原子:

?- sub_atom(Word, 0, 1, _, First), vowel(First).
你可以很容易地把几乎任何东西转换成原子。例如,见

如果原子的第一个字符是元音,则此查询将成功,否则将失败。要使其成为谓词,请执行以下操作:

first_letter_vowel(Word) :-
    sub_atom(Word, 0, 1, _, First),
    vowel(First).
或者,例如:

nth_letter_vowel(N, Word) :-
    sub_atom(Word, N, 1, _, Letter),
    vowel(Letter).
如果您使用的是SWI Prolog,还可以使用downcase\u atom/2:

nth_letter_vowel(N, Word) :-
    sub_atom(Word, N, 1, _, Letter),
    downcase_atom(Letter, Lower_Case),
    vowel(Lower_Case).
编辑:为什么是事实表而不是
member/2
memberchk/2

它更干净;它的内存效率更高,速度更快;它使计划的意图显而易见;这是(并且一直是)首选的方式:查看最底层(顺便说一句,它讨论了许多有趣的事情)

以下是使用
元音/1
的可能查询的详尽列表,这些查询被定义为事实表:

?- vowel(r).
false.

?- vowel(i).
true.

?- vowel(V).
V = a ;
V = e ;
V = i ;
V = o ;
V = u.

?- vowel(foobar(baz)). % or anything, really
false.
现在我们知道
member/2
将留下选择点,因此
memberchk/2
肯定是首选(除非我们打算使用选择点!)。但即便如此:

?- memberchk(a, [a,b,c]).
true. % that's fine

?- memberchk(x, [a,b,c]).
false. % ok

?- memberchk(a, L).
L = [a|_G1190]. % what?

?- memberchk(X, [a,b,c]).
X = a. % what?

因此,是的,在原始问题的上下文中,假设我们确保仔细检查
member/2
memberchk/2
的参数,选择事实表的原因只是风格和“实用”(内存效率、速度).

与使用
member/2
memberchk/2
相比,使用
元音/1
的直接表示法有什么好处(除了满足目标所需的推理数量上的微小差异)?@TudorBerariu这是一个很长的话题;请看对我原始答案的编辑。实际上并不缺少资源。检查标签信息,以获得非常好的在线教程和书籍选择()。我一直认为DCG代表Definite子句Grammar@CapelliC哎呀!谢谢你注意到我的打字错误。很抱歉我的回复太晚了-谢谢你花时间帮助我:)这正是我想要的,泰