我需要根据我的事实构建一个列表。例如,我有一个这样的课程列表:
attend(student1,c1).
attend(student1,c2).
attend(student2,c1).
attend(student2,c3).
现在我想要一个谓词courselist / 2,它返回给定学生的课程列表。当然,每个课程只应在此列表中一次。我不能使用像findall这样的内置谓词,但我可以使用成员或追加。到目前为止,我有这样的事情:
courselist(S,R) :- attend(S,C), member(C,R), courselist(S,R).
courselist(S,R) :- attend(S,C), append([C],L,R), courselist(S,R).
我知道这是错的,但我不知道如何在不进入无限循环的情况下找到所有事实。
答案 0 :(得分:2)
这是一个愚蠢的限制,你不能使用findall/3
,因为它是这种问题的自然解决方案。你可以像这样手动完成:
student_courses(Student, Courses) :-
student_courses(Student, [], Courses).
student_courses(S, Cs0, Cs) :-
( attend(S, C), \+ member(C, Cs0) ->
student_courses(S, [C|Cs0], Cs)
; Cs = Cs0
).
示例查询:
?- student_courses(student2, Cs).
Cs = [c3, c1].
请注意,这不是真正的关系,因为此特定解决方案未出现在以下更一般的查询中:
?- student_courses(Student, Cs).
Student = student1,
Cs = [c2, c1].
我将它作为练习让您以最通用的查询产生所有正确结果的方式实现它。还要注意更可读和关系的谓词名称。