我是 Prolog 新手。以下谓词应该处理一个字符串列表,每个字符串包含以空格分隔的名字和姓氏。它的目的是遍历每个元素,用空格将其分隔为一个用于 FirstName 的元素和另一个用于 LastName 的元素,并将这些值添加到 FirstNames 列表和 LastNames 列表中。最后,它应该返回所有名字和姓氏的列表,两者都与原始列表的顺序相对应。我正在努力让它发挥作用。
populate([]).
populate([H|T], FirstNames, LastNames) :-
split_string(H, " ", " ", Elems),
Elems = [FirstName, LastName],
append(FirstNames, [FirstName], FirstNames2),
append(LastNames, [LastName], LastNames2),
populate(T, FirstNames, LastNames).
例如,如果给定
?- populate(["Peter Parker", "Bruce Wayne"], FirstNames, LastNames),
应该会回来
FirstNames = ["Peter", "Bruce"]
和
LastNames = ["Parker", "Wayne"].
在 SWI-Prolog 中对问题进行编码,具有以下特点:
dcg/basics
,更准确地使用规则 nonblanks//1
和 blank//0
分别处理非空白和单字符空白atom_codes/2
来拆分和重组文本来尊重这一点 - 'John Wayne'
) 而不是 SWI-Prolog 字符串 ("John Wayne"
)。所以:
首先使用 DCG 编写一个小谓词,将“名称原子”分解为“名字原子”和“姓氏原子”:
:- use_module(library(dcg/basics)).
name(First,Last) -->
nonblanks(FirstCodes), % collect a list of codes for the first name
blank, % then comes a blank
nonblanks(LastCodes), % collect a list of codes for the last name
{ atom_codes(First,FirstCodes), % fuse the codes into a "first name atom"
atom_codes(Last,LastCodes) }. % fuse the codes into a "last name atom"
separate(Name,First,Last) :-
atom_codes(Name,NameCodes),
phrase(name(First,Last),NameCodes).
separate/3
我们可以测试一下:
:- begin_tests(separate).
test(1) :-
separate('Bruce Wayne',First,Last),
assertion(First == 'Bruce'),
assertion(Last == 'Wayne').
:- end_tests(separate).
运行测试用例看起来不错:
?- run_tests(separate).
% PL-Unit: separate . done
% test passed
true.
现在我们只需要将
separate/3
应用于姓名列表即可。我们可以使用 maplist/3
但我们只使用递归定义:
% separate_all(+ListOfNames,-ListOfFirsts,.ListOfLasts)
separate_all([],[],[]).
separate_all([Name|Ns],[First|Fs],[Last|Ls]) :-
separate(Name,First,Last),
separate_all(Ns,Fs,Ls).
还有一个测试用例:
:- begin_tests(separate_all).
test(all_1) :-
separate_all(['Peter Parker', 'Bruce Wayne'],FirstNames,LastNames),
assertion(FirstNames == ['Peter','Bruce']),
assertion(LastNames == ['Parker','Wayne']).
:- end_tests(separate_all).
所以:
?- run_tests(separate_all).
% PL-Unit: separate_all . done
% test passed
true.