我有以下事实
%exam(Student,Subject)
exam(student1,subject1).
exam(student2,subject1).
exam(student3,subject1).
exam(student1,subject2).
exam(student3,subject2).
exam(student1,subject3).
我想找到学生的科目并将其列入名单
Subjects(Student,[H|T]):-
exam(Student,Subject),
\\+Subject=H,
H = Subject,
Subjects(Student,T).
我无法弄清楚基本情况应该是什么!
答案 0 :(得分:1)
\+ Subject = H
表示“无法证明”Subject
可以与H
统一。
但是,由于H
开始未经实例化,因此可以始终与Subject
统一,因此目标始终会失败。
此外,要查看之前是否找到Subject
,您必须在之前找到的值的列表中检查其成员资格。这意味着,在call to call中携带一个额外的参数,该参数将从[]
开始,将新发现的主题添加到其中,并使用更新的列表进行下一次调用。
只要您能找到新的事实,就可以将其添加到此累积列表中,然后继续;但如果你找不到新的事实,你应该停下来。这将是你的基本情况。使用辅助谓词进行编码会更容易,每个辅助谓词都执行单独的任务(如can_find_new_subject( Student, ListSeenSoFar, Subject)
等)。
subjects(Student, L):- search_subjects(Student, [], L).
search_subjects(Student, Seen, L):-
find_new_subject(Student, Seen, Subj)
search_subjects(Student, [Subj|Seen], L).
search_subjects(Student, Seen, L):-
\+ find_new_subject(Student, Seen, Subj),
... .
find_new_subject( ......
....
这种设置的缺点是它将是二次的。如果没有像assert
这样的额外逻辑工具,或者使用内置的findall
等,您就无法使其成为线性。