2

我有一个单词列表,例如 [cola,fanta,pepsi],我想编写一个谓词来检查是否有任何元素以指定的字符开头。

到目前为止,我的代码如下:

chk_first_letter(Char,[]):-fail.
chk_first_letter(Char, [H|T]):-
    perform_check(Char, H);
    chk_first_letter(Char, T).
perform_check(Char,[First|_]):-memberchk(Char, First).

但是,即使百事可乐以 p 开头,查阅我的文件并调用 chk_first_letter(p,[cola,fanta,pepsi]) 也不会给我任何帮助。

我试过用 Char==First 而不是 memberchk(Char,First) 但它也没有用。我不确定区别。

4

3 回答 3

4

You have a list of atoms, and your perform_check/2 compares two atoms. An atom is not a list of characters! You need to use atom processing, for example:

perform_check(First, Word) :-
    sub_atom(Word, 0, 1, _After, First).

http://gprolog.univ-paris1.fr/manual/html_node/gprolog043.html#sec200

There are a bunch of other built-ins in this section that could be used, for example for breaking the atom into characters or character codes (atom_chars/2 and atom_codes/2). But what sub_atom/5 also allows you to do easily:

prefixes of any length:

sub_atom(Word, 0, _Length, _After, Prefix).

suffixes:

sub_atom(Word, _Before, _Length, 0, Suffix).
于 2013-09-19T12:37:57.053 回答
3

第一次尝试:

chk_first_letter(Char, Atoms) :- member(A, Atoms), atom_chars(A, [Char|_]).

atom_chars /2 这是一个 ISO 谓词。

你的代码几乎可以工作了,可以这样简化:

chk_first_letter(Char, [H|T]):-
    atom_chars(H, [Char|_]);
    chk_first_letter(Char, T).
于 2013-09-19T12:59:02.033 回答
2

memberchk期望以列表作为第二个参数调用。在您的情况下,您为它提供了一个字符。

然后您可能可以通过利用统一来完全取消它:

perform_check(Char,[Char|_]).

这假设您的字符串类型是字符列表(无论字符格式如何)。如果你打算直接对原子进行操作,你可以这样做:

perform_check(Char,String) :- atom_concat(Char,_,String)

将有更多的步骤来使您的代码更加地道,但这似乎是它的实际错误部分。

于 2013-09-19T12:11:37.753 回答