我对他们所做的学生和运动有所谓,我想知道哪些学生做了特定的运动。我有这个音乐,但是如果我在列表中输入精确的运动,我只能得到结果,而我的查找谓词只能在列表中找到一项运动。我不知道怎么把它组合在一起用来找到做运动的学生:
student('Quinton Tarentino', male, 12).
student('Tom Hanks', male, 9).
student('Ed Harris', male, 11).
does_sport('Quinton Tarentino', [soccer, hockey, cricket]).
does_sport('Tom Hanks', []).
does_sport('Ed Harris', [hockey, swimming]).
sports([soccer, hockey, swimming, cricket, netball]).
find(X) :- sports(L), member(X, L).
我尝试过这样的事情:
?- does_sport(X, find(soccer, L)).
这只是返回false。我知道我需要将我的体育列表链接到does_sports谓词,但不确定如何。
任何建议表示赞赏:)
答案 0 :(得分:2)
要找出哪些学生参与某项运动,您可以定义一个谓词:
student_sport(St,Sp) :-
does_sport(St,L), % L is a list of sports student St does
member(Sp,L). % Sp is a member of list L
然后你可以查询例如足球,正如你似乎打算在你的问题中那样,如下:
?- student_sport(St,soccer).
St = 'Quintin Tarentino' ? ;
no
另一方面,曲棍球产生了两个结果:
?- student_sport(St,hockey).
St = 'Quintin Tarentino' ? ;
St = 'Ed Harris' ? ;
no
如果你想要一个学生做曲棍球的学生名单,你可以这样使用findall/3
:
?- findall(St,student_sport(St,hockey),L).
L = ['Quintin Tarentino','Ed Harris']
或者setof/3
来获取排序列表(没有重复项,以防您碰巧有包含任何事实的事实):
?- setof(St,student_sport(St,hockey),L).
L = ['Ed Harris','Quintin Tarentino']
请注意,在某些Prolog中,您可能必须明确包含要使用member/2
的库,例如在Yap::- use_module(library(lists)).
,而其他人则自动加载,例如SWI。
关于您在评论中提出的问题,让我们开始观察student_sport/2
一次产生一个答案。这是有意的,正如包含单词 student 的谓词名称所暗示的那样:它描述了学生和学生练习的特定运动之间的关系。这就是我使用findall/3
和setof/3
添加示例查询的原因,以展示如何在列表中收集解决方案。您可以轻松定义谓词students_sport/2
,该谓词描述特定运动与实践该运动的所有学生名单之间的关系:
students_sport(L,Sp) :-
setof(St,student_sport(St,Sp),L).
关于体育 - 严肃,你可以选择一个原子来表示这种情况,比如none
,然后像student_sport/2
那样添加一个相应的规则:
student_sport(St,none) :- % <- rule for the sports-austere
does_sport(St,[]). % <- succeeds if the student does no sport
student_sport(St,Sp) :-
does_sport(St,L),
member(Sp,L).
这会产生以下结果:
?- student_sport(St,none).
St = 'Tom Hanks' ? ;
no
?- students_sport(St,none).
St = ['Tom Hanks']
?- students_sport(St,hockey).
St = ['Ed Harris','Quintin Tarentino']
?- students_sport(St,Sp).
Sp = cricket,
St = ['Quintin Tarentino'] ? ;
Sp = hockey,
St = ['Ed Harris','Quintin Tarentino'] ? ;
Sp = none,
St = ['Tom Hanks'] ? ;
Sp = soccer,
St = ['Quintin Tarentino'] ? ;
Sp = swimming,
St = ['Ed Harris']
最后,关于你对代码的假设与我写的完全一样:结构中有一个相似之处,即你的谓词find/1
有第一个目标(sports/1
)涉及一个列表,随后使用member/2
检查该列表中的成员身份。 student_sport/2
的第二个规则(或编辑前的单个规则)也有第一个目标(但不同的一个:does_sport/2
)涉及一个列表,随后使用member/2
来检查成员身份在那个清单中。这里的相似之处结束了。我提供的版本根本没有使用sports/1
,而是does_sport/2
中与特定学生相关的体育列表。请注意,find/1
并未描述与学生的任何关联。此外,您的查询?- does_sport(X, find(soccer, L)).
表示您似乎期望某种返回值。您可以将谓词视为返回true
或false
的函数,但在编写Prolog时通常不太有用。参数find(soccer,L)
没有像您期望的那样被调用,而是直接作为参数传递。因为你的事实不包含某些内容
does_sport(*SomeStudentHere*, find(soccer,L)).
您的查询失败。