我的回答是以SWI-Prolog为主,我提到的任何内置谓词的详细信息都可以通过
搜索文档获得。但是,我认为我在这里说的一切都适用于其他重要的Prolog实现。如果我错了,请纠正我。
在Prolog中,我们使用
谓词而不是
函数(或者只使用返回真值的函数)。我将使用以下谓词来引用您的示例列表中的Prolog查询:
ex([ [005,"Chester",100],[001,"Bob",99],[002,"Andy",77] ]).
为了将格式化文本写入标准输出流,我们将使用谓词format/2
。它的签名是format(+Format, :Arguments)
,其中Format
是一个包含特殊序列以便插值的原子。转义序列以波浪线~
开头,完整菜单可以在SWI-Prolo 关于format/2
的文档中找到。Arguments
是用于替换Format
中序列的Prolog术语列表。在这个例子中,我们只需要~w
,它会写入一个参数和~n
,它会写入一个新行。作为一个通用的例子:例如,
?- format('Write ~w, then ~w, followed by ~w~n~n', ['this', 'that', 'the other']).
Write this, then that, followed by the other
true.
你将一个人表示为
[ID,姓名,成绩]
的列表形式,因此我们只需要编写一个谓词,让我们能够添加“No.N”中的
N
,然后我们可以使用这个人员列表作为
format/2
的其余参数。
display_person(N, Person) :-
format('No.~w: ID="~w", Name="~w", Grade=~w~n', [N|Person]).
在
format/2
的第二个参数中,
N
作为参数列表的头部前缀。我们可以这样测试谓词:
?- ex([P|Ps]), display_person(1, P).
No.1: ID="5", Name="Chester", Grade=100
P = [5, "Chester", 100],
Ps = [[1, "Bob", 99], [2, "Andy", 77]].
这样就完成了每个人员列表的显示。现在我们只需要遍历您的人员列表并显示每个成员。我们需要一个双位谓词来跟踪“No.N”部分显示的增加值,但我们只需要一个单位谓词将列表传递给显示谓词。这个要求导致我们使用常见的模式,即使用由辅助谓词支持的前端谓词:
display_people(People) :-
display_people(1, People). %% 使用起始值1初始化对display_people/2的调用
display_people(_, []).
display_people(N, [Person|People]) :-
display_person(N, Person),
M is N+1,
display_people(M, People).
使用ex/1
中的列表运行测试:
?- ex(Ps), display_people(Ps).
No.1: ID="5", Name="Chester", Grade=100
No.2: ID="1", Name="Bob", Grade=99
No.3: ID="2", Name="Andy", Grade=77
Ps = [[5, "Chester", 100], [1, "Bob", 99], [2, "Andy", 77]] ;
false.
然而,模式
p([X|Xs]) :- q(X), p(Xs)
正是
maplist/n
谓词所用的,因此我们可以节省一些打字,并通过编写以下内容来使程序的声明性含义更加清晰:
display_people(People) :-
length(People, NumPeople),
numlist(1, NumPeople, Nums),
maplist(display_person, Nums, People).
numlist(Low, High, Nums)
返回一个列表 Nums
,其中包含从 Low
到 High
的值。在上述定义中,maplist(display_person, Nums, People)
会基本上为每一对 N
在 Nums
中以及 P
在 People
中调用 display_person(N, P)
。
:)
- gniourf_gniourfs”更改为“a”,以便它能够在Unix中与我的字符串一起正常工作。在SWI-Prolog上,它完美地工作了。猜想这是因为我的字符串存储在单引号中的缘故? - GeorgeCostanzas”的错误,所以我把它改成了a。再次感谢。 - GeorgeCostanza